VirtualBox

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

Last change on this file since 37950 was 37466, checked in by vboxsync, 13 years ago

VMM,Devices: Automatically use a per-device lock instead of the giant IOM lock. With exception of the PIC, APIC, IOAPIC and PCI buses which are all using the PDM crit sect, there should be no calls between devices. So, this change should be relatively safe.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 144.4 KB
Line 
1/* $Id: PDMDevHlp.cpp 37466 2011-06-15 12:44:16Z 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,pfnDBGFTraceBuf} */
1004static DECLCALLBACK(RTTRACEBUF) pdmR3DevHlp_DBGFTraceBuf(PPDMDEVINS pDevIns)
1005{
1006 PDMDEV_ASSERT_DEVINS(pDevIns);
1007 RTTRACEBUF hTraceBuf = pDevIns->Internal.s.pVMR3->hTraceBufR3;
1008 LogFlow(("pdmR3DevHlp_DBGFTraceBuf: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, hTraceBuf));
1009 return hTraceBuf;
1010}
1011
1012
1013/** @interface_method_impl{PDMDEVHLPR3,pfnSTAMRegister} */
1014static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
1015{
1016 PDMDEV_ASSERT_DEVINS(pDevIns);
1017 PVM pVM = pDevIns->Internal.s.pVMR3;
1018 VM_ASSERT_EMT(pVM);
1019
1020 STAM_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc);
1021 NOREF(pVM);
1022}
1023
1024
1025
1026/** @interface_method_impl{PDMDEVHLPR3,pfnSTAMRegisterF} */
1027static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
1028 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...)
1029{
1030 PDMDEV_ASSERT_DEVINS(pDevIns);
1031 PVM pVM = pDevIns->Internal.s.pVMR3;
1032 VM_ASSERT_EMT(pVM);
1033
1034 va_list args;
1035 va_start(args, pszName);
1036 int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
1037 va_end(args);
1038 AssertRC(rc);
1039
1040 NOREF(pVM);
1041}
1042
1043
1044/** @interface_method_impl{PDMDEVHLPR3,pfnSTAMRegisterV} */
1045static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
1046 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)
1047{
1048 PDMDEV_ASSERT_DEVINS(pDevIns);
1049 PVM pVM = pDevIns->Internal.s.pVMR3;
1050 VM_ASSERT_EMT(pVM);
1051
1052 int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
1053 AssertRC(rc);
1054
1055 NOREF(pVM);
1056}
1057
1058
1059/** @interface_method_impl{PDMDEVHLPR3,pfnPCIRegister} */
1060static DECLCALLBACK(int) pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev)
1061{
1062 PDMDEV_ASSERT_DEVINS(pDevIns);
1063 PVM pVM = pDevIns->Internal.s.pVMR3;
1064 VM_ASSERT_EMT(pVM);
1065 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: pPciDev=%p:{.config={%#.256Rhxs}\n",
1066 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->config));
1067
1068 /*
1069 * Validate input.
1070 */
1071 if (!pPciDev)
1072 {
1073 Assert(pPciDev);
1074 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc (pPciDev)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1075 return VERR_INVALID_PARAMETER;
1076 }
1077 if (!pPciDev->config[0] && !pPciDev->config[1])
1078 {
1079 Assert(pPciDev->config[0] || pPciDev->config[1]);
1080 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc (vendor)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1081 return VERR_INVALID_PARAMETER;
1082 }
1083 if (pDevIns->Internal.s.pPciDeviceR3)
1084 {
1085 /** @todo the PCI device vs. PDM device designed is a bit flawed if we have to
1086 * support a PDM device with multiple PCI devices. This might become a problem
1087 * when upgrading the chipset for instance because of multiple functions in some
1088 * devices...
1089 */
1090 AssertMsgFailed(("Only one PCI device per device is currently implemented!\n"));
1091 return VERR_INTERNAL_ERROR;
1092 }
1093
1094 /*
1095 * Choose the PCI bus for the device.
1096 *
1097 * This is simple. If the device was configured for a particular bus, the PCIBusNo
1098 * configuration value will be set. If not the default bus is 0.
1099 */
1100 int rc;
1101 PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
1102 if (!pBus)
1103 {
1104 uint8_t u8Bus;
1105 rc = CFGMR3QueryU8Def(pDevIns->Internal.s.pCfgHandle, "PCIBusNo", &u8Bus, 0);
1106 AssertLogRelMsgRCReturn(rc, ("Configuration error: PCIBusNo query failed with rc=%Rrc (%s/%d)\n",
1107 rc, pDevIns->pReg->szName, pDevIns->iInstance), rc);
1108 AssertLogRelMsgReturn(u8Bus < RT_ELEMENTS(pVM->pdm.s.aPciBuses),
1109 ("Configuration error: PCIBusNo=%d, max is %d. (%s/%d)\n", u8Bus,
1110 RT_ELEMENTS(pVM->pdm.s.aPciBuses), pDevIns->pReg->szName, pDevIns->iInstance),
1111 VERR_PDM_NO_PCI_BUS);
1112 pBus = pDevIns->Internal.s.pPciBusR3 = &pVM->pdm.s.aPciBuses[u8Bus];
1113 }
1114 if (pBus->pDevInsR3)
1115 {
1116 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
1117 pDevIns->Internal.s.pPciBusR0 = MMHyperR3ToR0(pVM, pDevIns->Internal.s.pPciBusR3);
1118 else
1119 pDevIns->Internal.s.pPciBusR0 = NIL_RTR0PTR;
1120
1121 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
1122 pDevIns->Internal.s.pPciBusRC = MMHyperR3ToRC(pVM, pDevIns->Internal.s.pPciBusR3);
1123 else
1124 pDevIns->Internal.s.pPciBusRC = NIL_RTRCPTR;
1125
1126 /*
1127 * Check the configuration for PCI device and function assignment.
1128 */
1129 int iDev = -1;
1130 uint8_t u8Device;
1131 rc = CFGMR3QueryU8(pDevIns->Internal.s.pCfgHandle, "PCIDeviceNo", &u8Device);
1132 if (RT_SUCCESS(rc))
1133 {
1134 if (u8Device > 31)
1135 {
1136 AssertMsgFailed(("Configuration error: PCIDeviceNo=%d, max is 31. (%s/%d)\n",
1137 u8Device, pDevIns->pReg->szName, pDevIns->iInstance));
1138 return VERR_INTERNAL_ERROR;
1139 }
1140
1141 uint8_t u8Function;
1142 rc = CFGMR3QueryU8(pDevIns->Internal.s.pCfgHandle, "PCIFunctionNo", &u8Function);
1143 if (RT_FAILURE(rc))
1144 {
1145 AssertMsgFailed(("Configuration error: PCIDeviceNo, but PCIFunctionNo query failed with rc=%Rrc (%s/%d)\n",
1146 rc, pDevIns->pReg->szName, pDevIns->iInstance));
1147 return rc;
1148 }
1149 if (u8Function > 7)
1150 {
1151 AssertMsgFailed(("Configuration error: PCIFunctionNo=%d, max is 7. (%s/%d)\n",
1152 u8Function, pDevIns->pReg->szName, pDevIns->iInstance));
1153 return VERR_INTERNAL_ERROR;
1154 }
1155 iDev = (u8Device << 3) | u8Function;
1156 }
1157 else if (rc != VERR_CFGM_VALUE_NOT_FOUND)
1158 {
1159 AssertMsgFailed(("Configuration error: PCIDeviceNo query failed with rc=%Rrc (%s/%d)\n",
1160 rc, pDevIns->pReg->szName, pDevIns->iInstance));
1161 return rc;
1162 }
1163
1164 /*
1165 * Call the pci bus device to do the actual registration.
1166 */
1167 pdmLock(pVM);
1168 rc = pBus->pfnRegisterR3(pBus->pDevInsR3, pPciDev, pDevIns->pReg->szName, iDev);
1169 pdmUnlock(pVM);
1170 if (RT_SUCCESS(rc))
1171 {
1172 pPciDev->pDevIns = pDevIns;
1173
1174 pDevIns->Internal.s.pPciDeviceR3 = pPciDev;
1175 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
1176 pDevIns->Internal.s.pPciDeviceR0 = MMHyperR3ToR0(pVM, pPciDev);
1177 else
1178 pDevIns->Internal.s.pPciDeviceR0 = NIL_RTR0PTR;
1179
1180 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
1181 pDevIns->Internal.s.pPciDeviceRC = MMHyperR3ToRC(pVM, pPciDev);
1182 else
1183 pDevIns->Internal.s.pPciDeviceRC = NIL_RTRCPTR;
1184
1185 Log(("PDM: Registered device '%s'/%d as PCI device %d on bus %d\n",
1186 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->devfn, pDevIns->Internal.s.pPciBusR3->iBus));
1187 }
1188 }
1189 else
1190 {
1191 AssertLogRelMsgFailed(("Configuration error: No PCI bus available. This could be related to init order too!\n"));
1192 rc = VERR_PDM_NO_PCI_BUS;
1193 }
1194
1195 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1196 return rc;
1197}
1198
1199
1200/** @interface_method_impl{PDMDEVHLPR3,pfnPCIIORegionRegister} */
1201static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
1202{
1203 PDMDEV_ASSERT_DEVINS(pDevIns);
1204 PVM pVM = pDevIns->Internal.s.pVMR3;
1205 VM_ASSERT_EMT(pVM);
1206 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: iRegion=%d cbRegion=%#x enmType=%d pfnCallback=%p\n",
1207 pDevIns->pReg->szName, pDevIns->iInstance, iRegion, cbRegion, enmType, pfnCallback));
1208
1209 /*
1210 * Validate input.
1211 */
1212 if (iRegion < 0 || iRegion >= PCI_NUM_REGIONS)
1213 {
1214 Assert(iRegion >= 0 && iRegion < PCI_NUM_REGIONS);
1215 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (iRegion)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1216 return VERR_INVALID_PARAMETER;
1217 }
1218 switch ((int)enmType)
1219 {
1220 case PCI_ADDRESS_SPACE_IO:
1221 /*
1222 * Sanity check: don't allow to register more than 32K of the PCI I/O space.
1223 */
1224 AssertMsgReturn(cbRegion <= _32K,
1225 ("caller='%s'/%d: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cbRegion),
1226 VERR_INVALID_PARAMETER);
1227 break;
1228
1229 case PCI_ADDRESS_SPACE_MEM:
1230 case PCI_ADDRESS_SPACE_MEM_PREFETCH:
1231 case PCI_ADDRESS_SPACE_MEM | PCI_ADDRESS_SPACE_BAR64:
1232 case PCI_ADDRESS_SPACE_MEM_PREFETCH | PCI_ADDRESS_SPACE_BAR64:
1233 /*
1234 * Sanity check: don't allow to register more than 512MB of the PCI MMIO space for
1235 * now. If this limit is increased beyond 2GB, adapt the aligned check below as well!
1236 */
1237 AssertMsgReturn(cbRegion <= 512 * _1M,
1238 ("caller='%s'/%d: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cbRegion),
1239 VERR_INVALID_PARAMETER);
1240 break;
1241 default:
1242 AssertMsgFailed(("enmType=%#x is unknown\n", enmType));
1243 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (enmType)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1244 return VERR_INVALID_PARAMETER;
1245 }
1246 if (!pfnCallback)
1247 {
1248 Assert(pfnCallback);
1249 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (callback)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1250 return VERR_INVALID_PARAMETER;
1251 }
1252 AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
1253
1254 /*
1255 * Must have a PCI device registered!
1256 */
1257 int rc;
1258 PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR3;
1259 if (pPciDev)
1260 {
1261 /*
1262 * We're currently restricted to page aligned MMIO regions.
1263 */
1264 if ( ((enmType & ~(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM_PREFETCH)) == PCI_ADDRESS_SPACE_MEM)
1265 && cbRegion != RT_ALIGN_32(cbRegion, PAGE_SIZE))
1266 {
1267 Log(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: aligning cbRegion %#x -> %#x\n",
1268 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, RT_ALIGN_32(cbRegion, PAGE_SIZE)));
1269 cbRegion = RT_ALIGN_32(cbRegion, PAGE_SIZE);
1270 }
1271
1272 /*
1273 * For registering PCI MMIO memory or PCI I/O memory, the size of the region must be a power of 2!
1274 */
1275 int iLastSet = ASMBitLastSetU32(cbRegion);
1276 Assert(iLastSet > 0);
1277 uint32_t cbRegionAligned = RT_BIT_32(iLastSet - 1);
1278 if (cbRegion > cbRegionAligned)
1279 cbRegion = cbRegionAligned * 2; /* round up */
1280
1281 PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
1282 Assert(pBus);
1283 pdmLock(pVM);
1284 rc = pBus->pfnIORegionRegisterR3(pBus->pDevInsR3, pPciDev, iRegion, cbRegion, enmType, pfnCallback);
1285 pdmUnlock(pVM);
1286 }
1287 else
1288 {
1289 AssertMsgFailed(("No PCI device registered!\n"));
1290 rc = VERR_PDM_NOT_PCI_DEVICE;
1291 }
1292
1293 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1294 return rc;
1295}
1296
1297
1298/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetConfigCallbacks} */
1299static DECLCALLBACK(void) pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
1300 PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
1301{
1302 PDMDEV_ASSERT_DEVINS(pDevIns);
1303 PVM pVM = pDevIns->Internal.s.pVMR3;
1304 VM_ASSERT_EMT(pVM);
1305 LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: pPciDev=%p pfnRead=%p ppfnReadOld=%p pfnWrite=%p ppfnWriteOld=%p\n",
1306 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld));
1307
1308 /*
1309 * Validate input and resolve defaults.
1310 */
1311 AssertPtr(pfnRead);
1312 AssertPtr(pfnWrite);
1313 AssertPtrNull(ppfnReadOld);
1314 AssertPtrNull(ppfnWriteOld);
1315 AssertPtrNull(pPciDev);
1316
1317 if (!pPciDev)
1318 pPciDev = pDevIns->Internal.s.pPciDeviceR3;
1319 AssertReleaseMsg(pPciDev, ("You must register your device first!\n"));
1320 PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
1321 AssertRelease(pBus);
1322 AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
1323
1324 /*
1325 * Do the job.
1326 */
1327 pdmLock(pVM);
1328 pBus->pfnSetConfigCallbacksR3(pBus->pDevInsR3, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld);
1329 pdmUnlock(pVM);
1330
1331 LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1332}
1333
1334
1335/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrq} */
1336static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
1337{
1338 PDMDEV_ASSERT_DEVINS(pDevIns);
1339 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
1340
1341 /*
1342 * Validate input.
1343 */
1344 /** @todo iIrq and iLevel checks. */
1345
1346 /*
1347 * Must have a PCI device registered!
1348 */
1349 PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR3;
1350 if (pPciDev)
1351 {
1352 PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3; /** @todo the bus should be associated with the PCI device not the PDM device. */
1353 Assert(pBus);
1354 PVM pVM = pDevIns->Internal.s.pVMR3;
1355 pdmLock(pVM);
1356 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel);
1357 pdmUnlock(pVM);
1358 }
1359 else
1360 AssertReleaseMsgFailed(("No PCI device registered!\n"));
1361
1362 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1363}
1364
1365
1366/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrqNoWait} */
1367static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
1368{
1369 pdmR3DevHlp_PCISetIrq(pDevIns, iIrq, iLevel);
1370}
1371
1372
1373/** @interface_method_impl{PDMDEVHLPR3,pfnPCIRegisterMsi} */
1374static DECLCALLBACK(int) pdmR3DevHlp_PCIRegisterMsi(PPDMDEVINS pDevIns, PPDMMSIREG pMsiReg)
1375{
1376 PDMDEV_ASSERT_DEVINS(pDevIns);
1377 LogFlow(("pdmR3DevHlp_PCIRegisterMsi: caller='%s'/%d: %d MSI vectors %d MSI-X vectors\n", pDevIns->pReg->szName, pDevIns->iInstance, pMsiReg->cMsiVectors,pMsiReg->cMsixVectors ));
1378 int rc = VINF_SUCCESS;
1379
1380 /*
1381 * Must have a PCI device registered!
1382 */
1383 PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR3;
1384 if (pPciDev)
1385 {
1386 PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3; /** @todo the bus should be associated with the PCI device not the PDM device. */
1387 Assert(pBus);
1388
1389 PVM pVM = pDevIns->Internal.s.pVMR3;
1390 pdmLock(pVM);
1391 if (!pBus->pfnRegisterMsiR3)
1392 rc = VERR_NOT_IMPLEMENTED;
1393 else
1394 rc = pBus->pfnRegisterMsiR3(pBus->pDevInsR3, pPciDev, pMsiReg);
1395 pdmUnlock(pVM);
1396 }
1397 else
1398 AssertReleaseMsgFailed(("No PCI device registered!\n"));
1399
1400 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1401 return rc;
1402}
1403
1404/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrq} */
1405static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
1406{
1407 PDMDEV_ASSERT_DEVINS(pDevIns);
1408 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
1409
1410 /*
1411 * Validate input.
1412 */
1413 /** @todo iIrq and iLevel checks. */
1414
1415 PVM pVM = pDevIns->Internal.s.pVMR3;
1416 PDMIsaSetIrq(pVM, iIrq, iLevel); /* (The API takes the lock.) */
1417
1418 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1419}
1420
1421
1422/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrqNoWait} */
1423static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
1424{
1425 pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
1426}
1427
1428
1429/** @interface_method_impl{PDMDEVHLPR3,pfnDriverAttach} */
1430static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
1431{
1432 PDMDEV_ASSERT_DEVINS(pDevIns);
1433 PVM pVM = pDevIns->Internal.s.pVMR3;
1434 VM_ASSERT_EMT(pVM);
1435 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
1436 pDevIns->pReg->szName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
1437
1438 /*
1439 * Lookup the LUN, it might already be registered.
1440 */
1441 PPDMLUN pLunPrev = NULL;
1442 PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;
1443 for (; pLun; pLunPrev = pLun, pLun = pLun->pNext)
1444 if (pLun->iLun == iLun)
1445 break;
1446
1447 /*
1448 * Create the LUN if if wasn't found, else check if driver is already attached to it.
1449 */
1450 if (!pLun)
1451 {
1452 if ( !pBaseInterface
1453 || !pszDesc
1454 || !*pszDesc)
1455 {
1456 Assert(pBaseInterface);
1457 Assert(pszDesc || *pszDesc);
1458 return VERR_INVALID_PARAMETER;
1459 }
1460
1461 pLun = (PPDMLUN)MMR3HeapAlloc(pVM, MM_TAG_PDM_LUN, sizeof(*pLun));
1462 if (!pLun)
1463 return VERR_NO_MEMORY;
1464
1465 pLun->iLun = iLun;
1466 pLun->pNext = pLunPrev ? pLunPrev->pNext : NULL;
1467 pLun->pTop = NULL;
1468 pLun->pBottom = NULL;
1469 pLun->pDevIns = pDevIns;
1470 pLun->pUsbIns = NULL;
1471 pLun->pszDesc = pszDesc;
1472 pLun->pBase = pBaseInterface;
1473 if (!pLunPrev)
1474 pDevIns->Internal.s.pLunsR3 = pLun;
1475 else
1476 pLunPrev->pNext = pLun;
1477 Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
1478 iLun, pszDesc, pDevIns->pReg->szName, pDevIns->iInstance));
1479 }
1480 else if (pLun->pTop)
1481 {
1482 AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
1483 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
1484 return VERR_PDM_DRIVER_ALREADY_ATTACHED;
1485 }
1486 Assert(pLun->pBase == pBaseInterface);
1487
1488
1489 /*
1490 * Get the attached driver configuration.
1491 */
1492 int rc;
1493 PCFGMNODE pNode = CFGMR3GetChildF(pDevIns->Internal.s.pCfgHandle, "LUN#%u", iLun);
1494 if (pNode)
1495 rc = pdmR3DrvInstantiate(pVM, pNode, pBaseInterface, NULL /*pDrvAbove*/, pLun, ppBaseInterface);
1496 else
1497 rc = VERR_PDM_NO_ATTACHED_DRIVER;
1498
1499
1500 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1501 return rc;
1502}
1503
1504
1505/** @interface_method_impl{PDMDEVHLPR3,pfnQueueCreate} */
1506static DECLCALLBACK(int) pdmR3DevHlp_QueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval,
1507 PFNPDMQUEUEDEV pfnCallback, bool fGCEnabled, const char *pszName, PPDMQUEUE *ppQueue)
1508{
1509 PDMDEV_ASSERT_DEVINS(pDevIns);
1510 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fGCEnabled=%RTbool pszName=%p:{%s} ppQueue=%p\n",
1511 pDevIns->pReg->szName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, pszName, pszName, ppQueue));
1512
1513 PVM pVM = pDevIns->Internal.s.pVMR3;
1514 VM_ASSERT_EMT(pVM);
1515
1516 if (pDevIns->iInstance > 0)
1517 {
1518 pszName = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s_%u", pszName, pDevIns->iInstance);
1519 AssertLogRelReturn(pszName, VERR_NO_MEMORY);
1520 }
1521
1522 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, pszName, ppQueue);
1523
1524 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *ppQueue));
1525 return rc;
1526}
1527
1528
1529/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectInit} */
1530static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
1531 const char *pszNameFmt, va_list va)
1532{
1533 PDMDEV_ASSERT_DEVINS(pDevIns);
1534 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszNameFmt=%p:{%s}\n",
1535 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pszNameFmt, pszNameFmt));
1536
1537 PVM pVM = pDevIns->Internal.s.pVMR3;
1538 VM_ASSERT_EMT(pVM);
1539 int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
1540
1541 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1542 return rc;
1543}
1544
1545
1546/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNop} */
1547static DECLCALLBACK(PPDMCRITSECT) pdmR3DevHlp_CritSectGetNop(PPDMDEVINS pDevIns)
1548{
1549 PDMDEV_ASSERT_DEVINS(pDevIns);
1550 PVM pVM = pDevIns->Internal.s.pVMR3;
1551 VM_ASSERT_EMT(pVM);
1552
1553 PPDMCRITSECT pCritSect = PDMR3CritSectGetNop(pVM);
1554 LogFlow(("pdmR3DevHlp_CritSectGetNop: caller='%s'/%d: return %p\n",
1555 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
1556 return pCritSect;
1557}
1558
1559
1560/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopR0} */
1561static DECLCALLBACK(R0PTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopR0(PPDMDEVINS pDevIns)
1562{
1563 PDMDEV_ASSERT_DEVINS(pDevIns);
1564 PVM pVM = pDevIns->Internal.s.pVMR3;
1565 VM_ASSERT_EMT(pVM);
1566
1567 R0PTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopR0(pVM);
1568 LogFlow(("pdmR3DevHlp_CritSectGetNopR0: caller='%s'/%d: return %RHv\n",
1569 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
1570 return pCritSect;
1571}
1572
1573
1574/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopRC} */
1575static DECLCALLBACK(RCPTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopRC(PPDMDEVINS pDevIns)
1576{
1577 PDMDEV_ASSERT_DEVINS(pDevIns);
1578 PVM pVM = pDevIns->Internal.s.pVMR3;
1579 VM_ASSERT_EMT(pVM);
1580
1581 RCPTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopRC(pVM);
1582 LogFlow(("pdmR3DevHlp_CritSectGetNopRC: caller='%s'/%d: return %RRv\n",
1583 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
1584 return pCritSect;
1585}
1586
1587
1588/** @interface_method_impl{PDMDEVHLPR3,pfnSetDeviceCritSect} */
1589static DECLCALLBACK(int) pdmR3DevHlp_SetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
1590{
1591 /*
1592 * Validate input.
1593 *
1594 * Note! We only allow the automatically created default critical section
1595 * to be replaced by this API.
1596 */
1597 PDMDEV_ASSERT_DEVINS(pDevIns);
1598 AssertPtrReturn(pCritSect, VERR_INVALID_POINTER);
1599 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: pCritSect=%p (%s)\n",
1600 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pCritSect->s.pszName));
1601 AssertReturn(PDMCritSectIsInitialized(pCritSect), VERR_INVALID_PARAMETER);
1602 PVM pVM = pDevIns->Internal.s.pVMR3;
1603 AssertReturn(pCritSect->s.pVMR3 == pVM, VERR_INVALID_PARAMETER);
1604
1605 VM_ASSERT_EMT(pVM);
1606 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1607
1608 AssertReturn(pDevIns->pCritSectRoR3, VERR_INTERNAL_ERROR_4);
1609 AssertReturn(pDevIns->pCritSectRoR3->s.fAutomaticDefaultCritsect, VERR_WRONG_ORDER);
1610 AssertReturn(!pDevIns->pCritSectRoR3->s.fUsedByTimerOrSimilar, VERR_WRONG_ORDER);
1611 AssertReturn(pDevIns->pCritSectRoR3 != pCritSect, VERR_INVALID_PARAMETER);
1612
1613 /*
1614 * Replace the critical section and destroy the automatic default section.
1615 */
1616 PPDMCRITSECT pOldCritSect = pDevIns->pCritSectRoR3;
1617 pDevIns->pCritSectRoR3 = pCritSect;
1618 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
1619 pDevIns->pCritSectRoR0 = MMHyperCCToR0(pVM, pDevIns->pCritSectRoR3);
1620 else
1621 Assert(pDevIns->pCritSectRoR0 == NIL_RTRCPTR);
1622
1623 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
1624 pDevIns->pCritSectRoRC = MMHyperCCToRC(pVM, pDevIns->pCritSectRoR3);
1625 else
1626 Assert(pDevIns->pCritSectRoRC == NIL_RTRCPTR);
1627
1628 PDMR3CritSectDelete(pOldCritSect);
1629 if (pDevIns->pReg->fFlags & (PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0))
1630 MMHyperFree(pVM, pOldCritSect);
1631 else
1632 MMR3HeapFree(pOldCritSect);
1633
1634 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
1635 return VINF_SUCCESS;
1636}
1637
1638
1639/** @interface_method_impl{PDMDEVHLPR3,pfnThreadCreate} */
1640static DECLCALLBACK(int) pdmR3DevHlp_ThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
1641 PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
1642{
1643 PDMDEV_ASSERT_DEVINS(pDevIns);
1644 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
1645 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
1646 pDevIns->pReg->szName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
1647
1648 int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
1649
1650 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDevIns->pReg->szName, pDevIns->iInstance,
1651 rc, *ppThread));
1652 return rc;
1653}
1654
1655
1656/** @interface_method_impl{PDMDEVHLPR3,pfnSetAsyncNotification} */
1657static DECLCALLBACK(int) pdmR3DevHlp_SetAsyncNotification(PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)
1658{
1659 PDMDEV_ASSERT_DEVINS(pDevIns);
1660 VM_ASSERT_EMT0(pDevIns->Internal.s.pVMR3);
1661 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: pfnAsyncNotify=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pfnAsyncNotify));
1662
1663 int rc = VINF_SUCCESS;
1664 AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
1665 AssertStmt(!pDevIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
1666 AssertStmt(pDevIns->Internal.s.fIntFlags & (PDMDEVINSINT_FLAGS_SUSPENDED | PDMDEVINSINT_FLAGS_RESET), rc = VERR_WRONG_ORDER);
1667 VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
1668 AssertStmt( enmVMState == VMSTATE_SUSPENDING
1669 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
1670 || enmVMState == VMSTATE_SUSPENDING_LS
1671 || enmVMState == VMSTATE_RESETTING
1672 || enmVMState == VMSTATE_RESETTING_LS
1673 || enmVMState == VMSTATE_POWERING_OFF
1674 || enmVMState == VMSTATE_POWERING_OFF_LS,
1675 rc = VERR_INVALID_STATE);
1676
1677 if (RT_SUCCESS(rc))
1678 pDevIns->Internal.s.pfnAsyncNotify = pfnAsyncNotify;
1679
1680 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1681 return rc;
1682}
1683
1684
1685/** @interface_method_impl{PDMDEVHLPR3,pfnAsyncNotificationCompleted} */
1686static DECLCALLBACK(void) pdmR3DevHlp_AsyncNotificationCompleted(PPDMDEVINS pDevIns)
1687{
1688 PDMDEV_ASSERT_DEVINS(pDevIns);
1689 PVM pVM = pDevIns->Internal.s.pVMR3;
1690
1691 VMSTATE enmVMState = VMR3GetState(pVM);
1692 if ( enmVMState == VMSTATE_SUSPENDING
1693 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
1694 || enmVMState == VMSTATE_SUSPENDING_LS
1695 || enmVMState == VMSTATE_RESETTING
1696 || enmVMState == VMSTATE_RESETTING_LS
1697 || enmVMState == VMSTATE_POWERING_OFF
1698 || enmVMState == VMSTATE_POWERING_OFF_LS)
1699 {
1700 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
1701 VMR3AsyncPdmNotificationWakeupU(pVM->pUVM);
1702 }
1703 else
1704 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d: enmVMState=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, enmVMState));
1705}
1706
1707
1708/** @interface_method_impl{PDMDEVHLPR3,pfnRTCRegister} */
1709static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
1710{
1711 PDMDEV_ASSERT_DEVINS(pDevIns);
1712 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
1713 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
1714 pDevIns->pReg->szName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
1715 pRtcReg->pfnWrite, ppRtcHlp));
1716
1717 /*
1718 * Validate input.
1719 */
1720 if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
1721 {
1722 AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
1723 PDM_RTCREG_VERSION));
1724 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (version)\n",
1725 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1726 return VERR_INVALID_PARAMETER;
1727 }
1728 if ( !pRtcReg->pfnWrite
1729 || !pRtcReg->pfnRead)
1730 {
1731 Assert(pRtcReg->pfnWrite);
1732 Assert(pRtcReg->pfnRead);
1733 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
1734 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1735 return VERR_INVALID_PARAMETER;
1736 }
1737
1738 if (!ppRtcHlp)
1739 {
1740 Assert(ppRtcHlp);
1741 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (ppRtcHlp)\n",
1742 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1743 return VERR_INVALID_PARAMETER;
1744 }
1745
1746 /*
1747 * Only one DMA device.
1748 */
1749 PVM pVM = pDevIns->Internal.s.pVMR3;
1750 if (pVM->pdm.s.pRtc)
1751 {
1752 AssertMsgFailed(("Only one RTC device is supported!\n"));
1753 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
1754 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1755 return VERR_INVALID_PARAMETER;
1756 }
1757
1758 /*
1759 * Allocate and initialize pci bus structure.
1760 */
1761 int rc = VINF_SUCCESS;
1762 PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
1763 if (pRtc)
1764 {
1765 pRtc->pDevIns = pDevIns;
1766 pRtc->Reg = *pRtcReg;
1767 pVM->pdm.s.pRtc = pRtc;
1768
1769 /* set the helper pointer. */
1770 *ppRtcHlp = &g_pdmR3DevRtcHlp;
1771 Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
1772 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
1773 }
1774 else
1775 rc = VERR_NO_MEMORY;
1776
1777 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
1778 pDevIns->pReg->szName, pDevIns->iInstance, rc));
1779 return rc;
1780}
1781
1782
1783/** @interface_method_impl{PDMDEVHLPR3,pfnDMARegister} */
1784static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
1785{
1786 PDMDEV_ASSERT_DEVINS(pDevIns);
1787 PVM pVM = pDevIns->Internal.s.pVMR3;
1788 VM_ASSERT_EMT(pVM);
1789 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
1790 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
1791 int rc = VINF_SUCCESS;
1792 if (pVM->pdm.s.pDmac)
1793 pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
1794 else
1795 {
1796 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
1797 rc = VERR_PDM_NO_DMAC_INSTANCE;
1798 }
1799 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Rrc\n",
1800 pDevIns->pReg->szName, pDevIns->iInstance, rc));
1801 return rc;
1802}
1803
1804
1805/** @interface_method_impl{PDMDEVHLPR3,pfnDMAReadMemory} */
1806static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
1807{
1808 PDMDEV_ASSERT_DEVINS(pDevIns);
1809 PVM pVM = pDevIns->Internal.s.pVMR3;
1810 VM_ASSERT_EMT(pVM);
1811 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
1812 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
1813 int rc = VINF_SUCCESS;
1814 if (pVM->pdm.s.pDmac)
1815 {
1816 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
1817 if (pcbRead)
1818 *pcbRead = cb;
1819 }
1820 else
1821 {
1822 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
1823 rc = VERR_PDM_NO_DMAC_INSTANCE;
1824 }
1825 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Rrc\n",
1826 pDevIns->pReg->szName, pDevIns->iInstance, rc));
1827 return rc;
1828}
1829
1830
1831/** @interface_method_impl{PDMDEVHLPR3,pfnDMAWriteMemory} */
1832static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
1833{
1834 PDMDEV_ASSERT_DEVINS(pDevIns);
1835 PVM pVM = pDevIns->Internal.s.pVMR3;
1836 VM_ASSERT_EMT(pVM);
1837 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
1838 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
1839 int rc = VINF_SUCCESS;
1840 if (pVM->pdm.s.pDmac)
1841 {
1842 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
1843 if (pcbWritten)
1844 *pcbWritten = cb;
1845 }
1846 else
1847 {
1848 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
1849 rc = VERR_PDM_NO_DMAC_INSTANCE;
1850 }
1851 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Rrc\n",
1852 pDevIns->pReg->szName, pDevIns->iInstance, rc));
1853 return rc;
1854}
1855
1856
1857/** @interface_method_impl{PDMDEVHLPR3,pfnDMASetDREQ} */
1858static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
1859{
1860 PDMDEV_ASSERT_DEVINS(pDevIns);
1861 PVM pVM = pDevIns->Internal.s.pVMR3;
1862 VM_ASSERT_EMT(pVM);
1863 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
1864 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, uLevel));
1865 int rc = VINF_SUCCESS;
1866 if (pVM->pdm.s.pDmac)
1867 pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
1868 else
1869 {
1870 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
1871 rc = VERR_PDM_NO_DMAC_INSTANCE;
1872 }
1873 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Rrc\n",
1874 pDevIns->pReg->szName, pDevIns->iInstance, rc));
1875 return rc;
1876}
1877
1878/** @interface_method_impl{PDMDEVHLPR3,pfnDMAGetChannelMode} */
1879static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
1880{
1881 PDMDEV_ASSERT_DEVINS(pDevIns);
1882 PVM pVM = pDevIns->Internal.s.pVMR3;
1883 VM_ASSERT_EMT(pVM);
1884 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
1885 pDevIns->pReg->szName, pDevIns->iInstance, uChannel));
1886 uint8_t u8Mode;
1887 if (pVM->pdm.s.pDmac)
1888 u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
1889 else
1890 {
1891 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
1892 u8Mode = 3 << 2 /* illegal mode type */;
1893 }
1894 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
1895 pDevIns->pReg->szName, pDevIns->iInstance, u8Mode));
1896 return u8Mode;
1897}
1898
1899/** @interface_method_impl{PDMDEVHLPR3,pfnDMASchedule} */
1900static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
1901{
1902 PDMDEV_ASSERT_DEVINS(pDevIns);
1903 PVM pVM = pDevIns->Internal.s.pVMR3;
1904 VM_ASSERT_EMT(pVM);
1905 LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
1906 pDevIns->pReg->szName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_PDM_DMA)));
1907
1908 AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
1909 VM_FF_SET(pVM, VM_FF_PDM_DMA);
1910 REMR3NotifyDmaPending(pVM);
1911 VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
1912}
1913
1914
1915/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSWrite} */
1916static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
1917{
1918 PDMDEV_ASSERT_DEVINS(pDevIns);
1919 PVM pVM = pDevIns->Internal.s.pVMR3;
1920 VM_ASSERT_EMT(pVM);
1921
1922 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
1923 pDevIns->pReg->szName, pDevIns->iInstance, iReg, u8Value));
1924 int rc;
1925 if (pVM->pdm.s.pRtc)
1926 rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pVM->pdm.s.pRtc->pDevIns, iReg, u8Value);
1927 else
1928 rc = VERR_PDM_NO_RTC_INSTANCE;
1929
1930 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
1931 pDevIns->pReg->szName, pDevIns->iInstance, rc));
1932 return rc;
1933}
1934
1935
1936/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSRead} */
1937static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
1938{
1939 PDMDEV_ASSERT_DEVINS(pDevIns);
1940 PVM pVM = pDevIns->Internal.s.pVMR3;
1941 VM_ASSERT_EMT(pVM);
1942
1943 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
1944 pDevIns->pReg->szName, pDevIns->iInstance, iReg, pu8Value));
1945 int rc;
1946 if (pVM->pdm.s.pRtc)
1947 rc = pVM->pdm.s.pRtc->Reg.pfnRead(pVM->pdm.s.pRtc->pDevIns, iReg, pu8Value);
1948 else
1949 rc = VERR_PDM_NO_RTC_INSTANCE;
1950
1951 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
1952 pDevIns->pReg->szName, pDevIns->iInstance, rc));
1953 return rc;
1954}
1955
1956
1957/** @interface_method_impl{PDMDEVHLPR3,pfnAssertEMT} */
1958static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
1959{
1960 PDMDEV_ASSERT_DEVINS(pDevIns);
1961 if (VM_IS_EMT(pDevIns->Internal.s.pVMR3))
1962 return true;
1963
1964 char szMsg[100];
1965 RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
1966 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
1967 AssertBreakpoint();
1968 return false;
1969}
1970
1971
1972/** @interface_method_impl{PDMDEVHLPR3,pfnAssertOther} */
1973static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
1974{
1975 PDMDEV_ASSERT_DEVINS(pDevIns);
1976 if (!VM_IS_EMT(pDevIns->Internal.s.pVMR3))
1977 return true;
1978
1979 char szMsg[100];
1980 RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
1981 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
1982 AssertBreakpoint();
1983 return false;
1984}
1985
1986
1987/** @interface_method_impl{PDMDEVHLP,pfnLdrGetRCInterfaceSymbols} */
1988static DECLCALLBACK(int) pdmR3DevHlp_LdrGetRCInterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
1989 const char *pszSymPrefix, const char *pszSymList)
1990{
1991 PDMDEV_ASSERT_DEVINS(pDevIns);
1992 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
1993 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
1994 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
1995
1996 int rc;
1997 if ( strncmp(pszSymPrefix, "dev", 3) == 0
1998 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
1999 {
2000 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
2001 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
2002 pvInterface, cbInterface,
2003 pDevIns->pReg->szRCMod, pDevIns->Internal.s.pDevR3->pszRCSearchPath,
2004 pszSymPrefix, pszSymList,
2005 false /*fRing0OrRC*/);
2006 else
2007 {
2008 AssertMsgFailed(("Not a raw-mode enabled driver\n"));
2009 rc = VERR_PERMISSION_DENIED;
2010 }
2011 }
2012 else
2013 {
2014 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
2015 pszSymPrefix, pDevIns->pReg->szName));
2016 rc = VERR_INVALID_NAME;
2017 }
2018
2019 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
2020 pDevIns->iInstance, rc));
2021 return rc;
2022}
2023
2024
2025/** @interface_method_impl{PDMDEVHLP,pfnLdrGetR0InterfaceSymbols} */
2026static DECLCALLBACK(int) pdmR3DevHlp_LdrGetR0InterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
2027 const char *pszSymPrefix, const char *pszSymList)
2028{
2029 PDMDEV_ASSERT_DEVINS(pDevIns);
2030 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2031 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
2032 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
2033
2034 int rc;
2035 if ( strncmp(pszSymPrefix, "dev", 3) == 0
2036 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
2037 {
2038 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
2039 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
2040 pvInterface, cbInterface,
2041 pDevIns->pReg->szR0Mod, pDevIns->Internal.s.pDevR3->pszR0SearchPath,
2042 pszSymPrefix, pszSymList,
2043 true /*fRing0OrRC*/);
2044 else
2045 {
2046 AssertMsgFailed(("Not a ring-0 enabled driver\n"));
2047 rc = VERR_PERMISSION_DENIED;
2048 }
2049 }
2050 else
2051 {
2052 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
2053 pszSymPrefix, pDevIns->pReg->szName));
2054 rc = VERR_INVALID_NAME;
2055 }
2056
2057 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
2058 pDevIns->iInstance, rc));
2059 return rc;
2060}
2061
2062
2063/** @interface_method_impl{PDMDEVHLP,pfnCallR0} */
2064static DECLCALLBACK(int) pdmR3DevHlp_CallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
2065{
2066 PDMDEV_ASSERT_DEVINS(pDevIns);
2067 PVM pVM = pDevIns->Internal.s.pVMR3;
2068 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2069 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: uOperation=%#x u64Arg=%#RX64\n",
2070 pDevIns->pReg->szName, pDevIns->iInstance, uOperation, u64Arg));
2071
2072 /*
2073 * Resolve the ring-0 entry point. There is not need to remember this like
2074 * we do for drivers since this is mainly for construction time hacks and
2075 * other things that aren't performance critical.
2076 */
2077 int rc;
2078 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
2079 {
2080 char szSymbol[ sizeof("devR0") + sizeof(pDevIns->pReg->szName) + sizeof("ReqHandler")];
2081 strcat(strcat(strcpy(szSymbol, "devR0"), pDevIns->pReg->szName), "ReqHandler");
2082 szSymbol[sizeof("devR0") - 1] = RT_C_TO_UPPER(szSymbol[sizeof("devR0") - 1]);
2083
2084 PFNPDMDRVREQHANDLERR0 pfnReqHandlerR0;
2085 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, szSymbol, &pfnReqHandlerR0);
2086 if (RT_SUCCESS(rc))
2087 {
2088 /*
2089 * Make the ring-0 call.
2090 */
2091 PDMDEVICECALLREQHANDLERREQ Req;
2092 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
2093 Req.Hdr.cbReq = sizeof(Req);
2094 Req.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
2095 Req.pfnReqHandlerR0 = pfnReqHandlerR0;
2096 Req.uOperation = uOperation;
2097 Req.u32Alignment = 0;
2098 Req.u64Arg = u64Arg;
2099 rc = SUPR3CallVMMR0Ex(pVM->pVMR0, NIL_VMCPUID, VMMR0_DO_PDM_DEVICE_CALL_REQ_HANDLER, 0, &Req.Hdr);
2100 }
2101 else
2102 pfnReqHandlerR0 = NIL_RTR0PTR;
2103 }
2104 else
2105 rc = VERR_ACCESS_DENIED;
2106 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
2107 pDevIns->iInstance, rc));
2108 return rc;
2109}
2110
2111
2112/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
2113static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
2114{
2115 PDMDEV_ASSERT_DEVINS(pDevIns);
2116 LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
2117 return pDevIns->Internal.s.pVMR3;
2118}
2119
2120
2121/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
2122static DECLCALLBACK(PVMCPU) pdmR3DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
2123{
2124 PDMDEV_ASSERT_DEVINS(pDevIns);
2125 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2126 LogFlow(("pdmR3DevHlp_GetVMCPU: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, VMMGetCpuId(pDevIns->Internal.s.pVMR3)));
2127 return VMMGetCpu(pDevIns->Internal.s.pVMR3);
2128}
2129
2130
2131/** @interface_method_impl{PDMDEVHLPR3,pfnPCIBusRegister} */
2132static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
2133{
2134 PDMDEV_ASSERT_DEVINS(pDevIns);
2135 PVM pVM = pDevIns->Internal.s.pVMR3;
2136 VM_ASSERT_EMT(pVM);
2137 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, .pfnSetIrqR3=%p, "
2138 ".pfnSaveExecR3=%p, .pfnLoadExecR3=%p, .pfnFakePCIBIOSR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppPciHlpR3=%p\n",
2139 pDevIns->pReg->szName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
2140 pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnSetIrqR3, pPciBusReg->pfnSaveExecR3, pPciBusReg->pfnLoadExecR3,
2141 pPciBusReg->pfnFakePCIBIOSR3, pPciBusReg->pszSetIrqRC, pPciBusReg->pszSetIrqRC, pPciBusReg->pszSetIrqR0, pPciBusReg->pszSetIrqR0, ppPciHlpR3));
2142
2143 /*
2144 * Validate the structure.
2145 */
2146 if (pPciBusReg->u32Version != PDM_PCIBUSREG_VERSION)
2147 {
2148 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREG_VERSION));
2149 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2150 return VERR_INVALID_PARAMETER;
2151 }
2152 if ( !pPciBusReg->pfnRegisterR3
2153 || !pPciBusReg->pfnIORegionRegisterR3
2154 || !pPciBusReg->pfnSetIrqR3
2155 || !pPciBusReg->pfnSaveExecR3
2156 || !pPciBusReg->pfnLoadExecR3
2157 || (!pPciBusReg->pfnFakePCIBIOSR3 && !pVM->pdm.s.aPciBuses[0].pDevInsR3)) /* Only the first bus needs to do the BIOS work. */
2158 {
2159 Assert(pPciBusReg->pfnRegisterR3);
2160 Assert(pPciBusReg->pfnIORegionRegisterR3);
2161 Assert(pPciBusReg->pfnSetIrqR3);
2162 Assert(pPciBusReg->pfnSaveExecR3);
2163 Assert(pPciBusReg->pfnLoadExecR3);
2164 Assert(pPciBusReg->pfnFakePCIBIOSR3);
2165 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc (R3 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2166 return VERR_INVALID_PARAMETER;
2167 }
2168 if ( pPciBusReg->pszSetIrqRC
2169 && !VALID_PTR(pPciBusReg->pszSetIrqRC))
2170 {
2171 Assert(VALID_PTR(pPciBusReg->pszSetIrqRC));
2172 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2173 return VERR_INVALID_PARAMETER;
2174 }
2175 if ( pPciBusReg->pszSetIrqR0
2176 && !VALID_PTR(pPciBusReg->pszSetIrqR0))
2177 {
2178 Assert(VALID_PTR(pPciBusReg->pszSetIrqR0));
2179 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2180 return VERR_INVALID_PARAMETER;
2181 }
2182 if (!ppPciHlpR3)
2183 {
2184 Assert(ppPciHlpR3);
2185 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc (ppPciHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2186 return VERR_INVALID_PARAMETER;
2187 }
2188
2189 /*
2190 * Find free PCI bus entry.
2191 */
2192 unsigned iBus = 0;
2193 for (iBus = 0; iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
2194 if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
2195 break;
2196 if (iBus >= RT_ELEMENTS(pVM->pdm.s.aPciBuses))
2197 {
2198 AssertMsgFailed(("Too many PCI buses. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aPciBuses)));
2199 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc (pci bus)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2200 return VERR_INVALID_PARAMETER;
2201 }
2202 PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
2203
2204 /*
2205 * Resolve and init the RC bits.
2206 */
2207 if (pPciBusReg->pszSetIrqRC)
2208 {
2209 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pPciBusReg->pszSetIrqRC, &pPciBus->pfnSetIrqRC);
2210 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pPciBusReg->pszSetIrqRC, rc));
2211 if (RT_FAILURE(rc))
2212 {
2213 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2214 return rc;
2215 }
2216 pPciBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
2217 }
2218 else
2219 {
2220 pPciBus->pfnSetIrqRC = 0;
2221 pPciBus->pDevInsRC = 0;
2222 }
2223
2224 /*
2225 * Resolve and init the R0 bits.
2226 */
2227 if (pPciBusReg->pszSetIrqR0)
2228 {
2229 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pPciBusReg->pszSetIrqR0, &pPciBus->pfnSetIrqR0);
2230 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pPciBusReg->pszSetIrqR0, rc));
2231 if (RT_FAILURE(rc))
2232 {
2233 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2234 return rc;
2235 }
2236 pPciBus->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
2237 }
2238 else
2239 {
2240 pPciBus->pfnSetIrqR0 = 0;
2241 pPciBus->pDevInsR0 = 0;
2242 }
2243
2244 /*
2245 * Init the R3 bits.
2246 */
2247 pPciBus->iBus = iBus;
2248 pPciBus->pDevInsR3 = pDevIns;
2249 pPciBus->pfnRegisterR3 = pPciBusReg->pfnRegisterR3;
2250 pPciBus->pfnRegisterMsiR3 = pPciBusReg->pfnRegisterMsiR3;
2251 pPciBus->pfnIORegionRegisterR3 = pPciBusReg->pfnIORegionRegisterR3;
2252 pPciBus->pfnSetConfigCallbacksR3 = pPciBusReg->pfnSetConfigCallbacksR3;
2253 pPciBus->pfnSetIrqR3 = pPciBusReg->pfnSetIrqR3;
2254 pPciBus->pfnSaveExecR3 = pPciBusReg->pfnSaveExecR3;
2255 pPciBus->pfnLoadExecR3 = pPciBusReg->pfnLoadExecR3;
2256 pPciBus->pfnFakePCIBIOSR3 = pPciBusReg->pfnFakePCIBIOSR3;
2257
2258 Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
2259
2260 /* set the helper pointer and return. */
2261 *ppPciHlpR3 = &g_pdmR3DevPciHlp;
2262 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
2263 return VINF_SUCCESS;
2264}
2265
2266
2267/** @interface_method_impl{PDMDEVHLPR3,pfnPICRegister} */
2268static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
2269{
2270 PDMDEV_ASSERT_DEVINS(pDevIns);
2271 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2272 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",
2273 pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrqR3, pPicReg->pfnGetInterruptR3,
2274 pPicReg->pszSetIrqRC, pPicReg->pszSetIrqRC, pPicReg->pszGetInterruptRC, pPicReg->pszGetInterruptRC,
2275 pPicReg->pszSetIrqR0, pPicReg->pszSetIrqR0, pPicReg->pszGetInterruptR0, pPicReg->pszGetInterruptR0,
2276 ppPicHlpR3));
2277
2278 /*
2279 * Validate input.
2280 */
2281 if (pPicReg->u32Version != PDM_PICREG_VERSION)
2282 {
2283 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPicReg->u32Version, PDM_PICREG_VERSION));
2284 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2285 return VERR_INVALID_PARAMETER;
2286 }
2287 if ( !pPicReg->pfnSetIrqR3
2288 || !pPicReg->pfnGetInterruptR3)
2289 {
2290 Assert(pPicReg->pfnSetIrqR3);
2291 Assert(pPicReg->pfnGetInterruptR3);
2292 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (R3 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2293 return VERR_INVALID_PARAMETER;
2294 }
2295 if ( ( pPicReg->pszSetIrqRC
2296 || pPicReg->pszGetInterruptRC)
2297 && ( !VALID_PTR(pPicReg->pszSetIrqRC)
2298 || !VALID_PTR(pPicReg->pszGetInterruptRC))
2299 )
2300 {
2301 Assert(VALID_PTR(pPicReg->pszSetIrqRC));
2302 Assert(VALID_PTR(pPicReg->pszGetInterruptRC));
2303 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (RC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2304 return VERR_INVALID_PARAMETER;
2305 }
2306 if ( pPicReg->pszSetIrqRC
2307 && !(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC))
2308 {
2309 Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC);
2310 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (RC flag)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2311 return VERR_INVALID_PARAMETER;
2312 }
2313 if ( pPicReg->pszSetIrqR0
2314 && !(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0))
2315 {
2316 Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0);
2317 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (R0 flag)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2318 return VERR_INVALID_PARAMETER;
2319 }
2320 if (!ppPicHlpR3)
2321 {
2322 Assert(ppPicHlpR3);
2323 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (ppPicHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2324 return VERR_INVALID_PARAMETER;
2325 }
2326
2327 /*
2328 * Only one PIC device.
2329 */
2330 PVM pVM = pDevIns->Internal.s.pVMR3;
2331 if (pVM->pdm.s.Pic.pDevInsR3)
2332 {
2333 AssertMsgFailed(("Only one pic device is supported!\n"));
2334 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2335 return VERR_INVALID_PARAMETER;
2336 }
2337
2338 /*
2339 * RC stuff.
2340 */
2341 if (pPicReg->pszSetIrqRC)
2342 {
2343 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pPicReg->pszSetIrqRC, &pVM->pdm.s.Pic.pfnSetIrqRC);
2344 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pPicReg->pszSetIrqRC, rc));
2345 if (RT_SUCCESS(rc))
2346 {
2347 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pPicReg->pszGetInterruptRC, &pVM->pdm.s.Pic.pfnGetInterruptRC);
2348 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pPicReg->pszGetInterruptRC, rc));
2349 }
2350 if (RT_FAILURE(rc))
2351 {
2352 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2353 return rc;
2354 }
2355 pVM->pdm.s.Pic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
2356 }
2357 else
2358 {
2359 pVM->pdm.s.Pic.pDevInsRC = 0;
2360 pVM->pdm.s.Pic.pfnSetIrqRC = 0;
2361 pVM->pdm.s.Pic.pfnGetInterruptRC = 0;
2362 }
2363
2364 /*
2365 * R0 stuff.
2366 */
2367 if (pPicReg->pszSetIrqR0)
2368 {
2369 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pPicReg->pszSetIrqR0, &pVM->pdm.s.Pic.pfnSetIrqR0);
2370 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pPicReg->pszSetIrqR0, rc));
2371 if (RT_SUCCESS(rc))
2372 {
2373 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pPicReg->pszGetInterruptR0, &pVM->pdm.s.Pic.pfnGetInterruptR0);
2374 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pPicReg->pszGetInterruptR0, rc));
2375 }
2376 if (RT_FAILURE(rc))
2377 {
2378 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2379 return rc;
2380 }
2381 pVM->pdm.s.Pic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
2382 Assert(pVM->pdm.s.Pic.pDevInsR0);
2383 }
2384 else
2385 {
2386 pVM->pdm.s.Pic.pfnSetIrqR0 = 0;
2387 pVM->pdm.s.Pic.pfnGetInterruptR0 = 0;
2388 pVM->pdm.s.Pic.pDevInsR0 = 0;
2389 }
2390
2391 /*
2392 * R3 stuff.
2393 */
2394 pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
2395 pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrqR3;
2396 pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterruptR3;
2397 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
2398
2399 /* set the helper pointer and return. */
2400 *ppPicHlpR3 = &g_pdmR3DevPicHlp;
2401 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
2402 return VINF_SUCCESS;
2403}
2404
2405
2406/** @interface_method_impl{PDMDEVHLPR3,pfnAPICRegister} */
2407static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
2408{
2409 PDMDEV_ASSERT_DEVINS(pDevIns);
2410 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2411 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: pApicReg=%p:{.u32Version=%#x, .pfnGetInterruptR3=%p, .pfnSetBaseR3=%p, .pfnGetBaseR3=%p, "
2412 ".pfnSetTPRR3=%p, .pfnGetTPRR3=%p, .pfnWriteMSR3=%p, .pfnReadMSR3=%p, .pfnBusDeliverR3=%p, .pfnLocalInterruptR3=%p, pszGetInterruptRC=%p:{%s}, pszSetBaseRC=%p:{%s}, pszGetBaseRC=%p:{%s}, "
2413 ".pszSetTPRRC=%p:{%s}, .pszGetTPRRC=%p:{%s}, .pszWriteMSRRC=%p:{%s}, .pszReadMSRRC=%p:{%s}, .pszBusDeliverRC=%p:{%s}, .pszLocalInterruptRC=%p:{%s}} ppApicHlpR3=%p\n",
2414 pDevIns->pReg->szName, pDevIns->iInstance, pApicReg, pApicReg->u32Version, pApicReg->pfnGetInterruptR3, pApicReg->pfnSetBaseR3,
2415 pApicReg->pfnGetBaseR3, pApicReg->pfnSetTPRR3, pApicReg->pfnGetTPRR3, pApicReg->pfnWriteMSRR3, pApicReg->pfnReadMSRR3, pApicReg->pfnBusDeliverR3, pApicReg->pfnLocalInterruptR3, pApicReg->pszGetInterruptRC,
2416 pApicReg->pszGetInterruptRC, pApicReg->pszSetBaseRC, pApicReg->pszSetBaseRC, pApicReg->pszGetBaseRC, pApicReg->pszGetBaseRC,
2417 pApicReg->pszSetTPRRC, pApicReg->pszSetTPRRC, pApicReg->pszGetTPRRC, pApicReg->pszGetTPRRC, pApicReg->pszWriteMSRRC, pApicReg->pszWriteMSRRC, pApicReg->pszReadMSRRC, pApicReg->pszReadMSRRC, pApicReg->pszBusDeliverRC,
2418 pApicReg->pszBusDeliverRC, pApicReg->pszLocalInterruptRC, pApicReg->pszLocalInterruptRC, ppApicHlpR3));
2419
2420 /*
2421 * Validate input.
2422 */
2423 if (pApicReg->u32Version != PDM_APICREG_VERSION)
2424 {
2425 AssertMsgFailed(("u32Version=%#x expected %#x\n", pApicReg->u32Version, PDM_APICREG_VERSION));
2426 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2427 return VERR_INVALID_PARAMETER;
2428 }
2429 if ( !pApicReg->pfnGetInterruptR3
2430 || !pApicReg->pfnHasPendingIrqR3
2431 || !pApicReg->pfnSetBaseR3
2432 || !pApicReg->pfnGetBaseR3
2433 || !pApicReg->pfnSetTPRR3
2434 || !pApicReg->pfnGetTPRR3
2435 || !pApicReg->pfnWriteMSRR3
2436 || !pApicReg->pfnReadMSRR3
2437 || !pApicReg->pfnBusDeliverR3
2438 || !pApicReg->pfnLocalInterruptR3)
2439 {
2440 Assert(pApicReg->pfnGetInterruptR3);
2441 Assert(pApicReg->pfnHasPendingIrqR3);
2442 Assert(pApicReg->pfnSetBaseR3);
2443 Assert(pApicReg->pfnGetBaseR3);
2444 Assert(pApicReg->pfnSetTPRR3);
2445 Assert(pApicReg->pfnGetTPRR3);
2446 Assert(pApicReg->pfnWriteMSRR3);
2447 Assert(pApicReg->pfnReadMSRR3);
2448 Assert(pApicReg->pfnBusDeliverR3);
2449 Assert(pApicReg->pfnLocalInterruptR3);
2450 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc (R3 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2451 return VERR_INVALID_PARAMETER;
2452 }
2453 if ( ( pApicReg->pszGetInterruptRC
2454 || pApicReg->pszHasPendingIrqRC
2455 || pApicReg->pszSetBaseRC
2456 || pApicReg->pszGetBaseRC
2457 || pApicReg->pszSetTPRRC
2458 || pApicReg->pszGetTPRRC
2459 || pApicReg->pszWriteMSRRC
2460 || pApicReg->pszReadMSRRC
2461 || pApicReg->pszBusDeliverRC
2462 || pApicReg->pszLocalInterruptRC)
2463 && ( !VALID_PTR(pApicReg->pszGetInterruptRC)
2464 || !VALID_PTR(pApicReg->pszHasPendingIrqRC)
2465 || !VALID_PTR(pApicReg->pszSetBaseRC)
2466 || !VALID_PTR(pApicReg->pszGetBaseRC)
2467 || !VALID_PTR(pApicReg->pszSetTPRRC)
2468 || !VALID_PTR(pApicReg->pszGetTPRRC)
2469 || !VALID_PTR(pApicReg->pszWriteMSRRC)
2470 || !VALID_PTR(pApicReg->pszReadMSRRC)
2471 || !VALID_PTR(pApicReg->pszBusDeliverRC)
2472 || !VALID_PTR(pApicReg->pszLocalInterruptRC))
2473 )
2474 {
2475 Assert(VALID_PTR(pApicReg->pszGetInterruptRC));
2476 Assert(VALID_PTR(pApicReg->pszHasPendingIrqRC));
2477 Assert(VALID_PTR(pApicReg->pszSetBaseRC));
2478 Assert(VALID_PTR(pApicReg->pszGetBaseRC));
2479 Assert(VALID_PTR(pApicReg->pszSetTPRRC));
2480 Assert(VALID_PTR(pApicReg->pszGetTPRRC));
2481 Assert(VALID_PTR(pApicReg->pszReadMSRRC));
2482 Assert(VALID_PTR(pApicReg->pszWriteMSRRC));
2483 Assert(VALID_PTR(pApicReg->pszBusDeliverRC));
2484 Assert(VALID_PTR(pApicReg->pszLocalInterruptRC));
2485 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc (RC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2486 return VERR_INVALID_PARAMETER;
2487 }
2488 if ( ( pApicReg->pszGetInterruptR0
2489 || pApicReg->pszHasPendingIrqR0
2490 || pApicReg->pszSetBaseR0
2491 || pApicReg->pszGetBaseR0
2492 || pApicReg->pszSetTPRR0
2493 || pApicReg->pszGetTPRR0
2494 || pApicReg->pszWriteMSRR0
2495 || pApicReg->pszReadMSRR0
2496 || pApicReg->pszBusDeliverR0
2497 || pApicReg->pszLocalInterruptR0)
2498 && ( !VALID_PTR(pApicReg->pszGetInterruptR0)
2499 || !VALID_PTR(pApicReg->pszHasPendingIrqR0)
2500 || !VALID_PTR(pApicReg->pszSetBaseR0)
2501 || !VALID_PTR(pApicReg->pszGetBaseR0)
2502 || !VALID_PTR(pApicReg->pszSetTPRR0)
2503 || !VALID_PTR(pApicReg->pszGetTPRR0)
2504 || !VALID_PTR(pApicReg->pszReadMSRR0)
2505 || !VALID_PTR(pApicReg->pszWriteMSRR0)
2506 || !VALID_PTR(pApicReg->pszBusDeliverR0)
2507 || !VALID_PTR(pApicReg->pszLocalInterruptR0))
2508 )
2509 {
2510 Assert(VALID_PTR(pApicReg->pszGetInterruptR0));
2511 Assert(VALID_PTR(pApicReg->pszHasPendingIrqR0));
2512 Assert(VALID_PTR(pApicReg->pszSetBaseR0));
2513 Assert(VALID_PTR(pApicReg->pszGetBaseR0));
2514 Assert(VALID_PTR(pApicReg->pszSetTPRR0));
2515 Assert(VALID_PTR(pApicReg->pszGetTPRR0));
2516 Assert(VALID_PTR(pApicReg->pszReadMSRR0));
2517 Assert(VALID_PTR(pApicReg->pszWriteMSRR0));
2518 Assert(VALID_PTR(pApicReg->pszBusDeliverR0));
2519 Assert(VALID_PTR(pApicReg->pszLocalInterruptR0));
2520 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc (R0 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2521 return VERR_INVALID_PARAMETER;
2522 }
2523 if (!ppApicHlpR3)
2524 {
2525 Assert(ppApicHlpR3);
2526 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc (ppApicHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2527 return VERR_INVALID_PARAMETER;
2528 }
2529
2530 /*
2531 * Only one APIC device. On SMP we have single logical device covering all LAPICs,
2532 * as they need to communicate and share state easily.
2533 */
2534 PVM pVM = pDevIns->Internal.s.pVMR3;
2535 if (pVM->pdm.s.Apic.pDevInsR3)
2536 {
2537 AssertMsgFailed(("Only one apic device is supported!\n"));
2538 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2539 return VERR_INVALID_PARAMETER;
2540 }
2541
2542 /*
2543 * Resolve & initialize the RC bits.
2544 */
2545 if (pApicReg->pszGetInterruptRC)
2546 {
2547 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pApicReg->pszGetInterruptRC, &pVM->pdm.s.Apic.pfnGetInterruptRC);
2548 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pApicReg->pszGetInterruptRC, rc));
2549 if (RT_SUCCESS(rc))
2550 {
2551 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pApicReg->pszHasPendingIrqRC, &pVM->pdm.s.Apic.pfnHasPendingIrqRC);
2552 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pApicReg->pszHasPendingIrqRC, rc));
2553 }
2554 if (RT_SUCCESS(rc))
2555 {
2556 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pApicReg->pszSetBaseRC, &pVM->pdm.s.Apic.pfnSetBaseRC);
2557 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pApicReg->pszSetBaseRC, rc));
2558 }
2559 if (RT_SUCCESS(rc))
2560 {
2561 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pApicReg->pszGetBaseRC, &pVM->pdm.s.Apic.pfnGetBaseRC);
2562 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pApicReg->pszGetBaseRC, rc));
2563 }
2564 if (RT_SUCCESS(rc))
2565 {
2566 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pApicReg->pszSetTPRRC, &pVM->pdm.s.Apic.pfnSetTPRRC);
2567 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pApicReg->pszSetTPRRC, rc));
2568 }
2569 if (RT_SUCCESS(rc))
2570 {
2571 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pApicReg->pszGetTPRRC, &pVM->pdm.s.Apic.pfnGetTPRRC);
2572 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pApicReg->pszGetTPRRC, rc));
2573 }
2574 if (RT_SUCCESS(rc))
2575 {
2576 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pApicReg->pszWriteMSRRC, &pVM->pdm.s.Apic.pfnWriteMSRRC);
2577 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pApicReg->pszWriteMSRRC, rc));
2578 }
2579 if (RT_SUCCESS(rc))
2580 {
2581 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pApicReg->pszReadMSRRC, &pVM->pdm.s.Apic.pfnReadMSRRC);
2582 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pApicReg->pszReadMSRRC, rc));
2583 }
2584 if (RT_SUCCESS(rc))
2585 {
2586 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pApicReg->pszBusDeliverRC, &pVM->pdm.s.Apic.pfnBusDeliverRC);
2587 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pApicReg->pszBusDeliverRC, rc));
2588 }
2589 if (RT_SUCCESS(rc))
2590 {
2591 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pApicReg->pszLocalInterruptRC, &pVM->pdm.s.Apic.pfnLocalInterruptRC);
2592 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pApicReg->pszLocalInterruptRC, rc));
2593 }
2594 if (RT_FAILURE(rc))
2595 {
2596 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2597 return rc;
2598 }
2599 pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
2600 }
2601 else
2602 {
2603 pVM->pdm.s.Apic.pDevInsRC = 0;
2604 pVM->pdm.s.Apic.pfnGetInterruptRC = 0;
2605 pVM->pdm.s.Apic.pfnHasPendingIrqRC = 0;
2606 pVM->pdm.s.Apic.pfnSetBaseRC = 0;
2607 pVM->pdm.s.Apic.pfnGetBaseRC = 0;
2608 pVM->pdm.s.Apic.pfnSetTPRRC = 0;
2609 pVM->pdm.s.Apic.pfnGetTPRRC = 0;
2610 pVM->pdm.s.Apic.pfnWriteMSRRC = 0;
2611 pVM->pdm.s.Apic.pfnReadMSRRC = 0;
2612 pVM->pdm.s.Apic.pfnBusDeliverRC = 0;
2613 pVM->pdm.s.Apic.pfnLocalInterruptRC = 0;
2614 }
2615
2616 /*
2617 * Resolve & initialize the R0 bits.
2618 */
2619 if (pApicReg->pszGetInterruptR0)
2620 {
2621 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pApicReg->pszGetInterruptR0, &pVM->pdm.s.Apic.pfnGetInterruptR0);
2622 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pApicReg->pszGetInterruptR0, rc));
2623 if (RT_SUCCESS(rc))
2624 {
2625 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pApicReg->pszHasPendingIrqR0, &pVM->pdm.s.Apic.pfnHasPendingIrqR0);
2626 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pApicReg->pszHasPendingIrqR0, rc));
2627 }
2628 if (RT_SUCCESS(rc))
2629 {
2630 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pApicReg->pszSetBaseR0, &pVM->pdm.s.Apic.pfnSetBaseR0);
2631 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pApicReg->pszSetBaseR0, rc));
2632 }
2633 if (RT_SUCCESS(rc))
2634 {
2635 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pApicReg->pszGetBaseR0, &pVM->pdm.s.Apic.pfnGetBaseR0);
2636 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pApicReg->pszGetBaseR0, rc));
2637 }
2638 if (RT_SUCCESS(rc))
2639 {
2640 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pApicReg->pszSetTPRR0, &pVM->pdm.s.Apic.pfnSetTPRR0);
2641 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pApicReg->pszSetTPRR0, rc));
2642 }
2643 if (RT_SUCCESS(rc))
2644 {
2645 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pApicReg->pszGetTPRR0, &pVM->pdm.s.Apic.pfnGetTPRR0);
2646 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pApicReg->pszGetTPRR0, rc));
2647 }
2648 if (RT_SUCCESS(rc))
2649 {
2650 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pApicReg->pszWriteMSRR0, &pVM->pdm.s.Apic.pfnWriteMSRR0);
2651 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pApicReg->pszWriteMSRR0, rc));
2652 }
2653 if (RT_SUCCESS(rc))
2654 {
2655 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pApicReg->pszReadMSRR0, &pVM->pdm.s.Apic.pfnReadMSRR0);
2656 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pApicReg->pszReadMSRR0, rc));
2657 }
2658 if (RT_SUCCESS(rc))
2659 {
2660 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pApicReg->pszBusDeliverR0, &pVM->pdm.s.Apic.pfnBusDeliverR0);
2661 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pApicReg->pszBusDeliverR0, rc));
2662 }
2663 if (RT_SUCCESS(rc))
2664 {
2665 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pApicReg->pszLocalInterruptR0, &pVM->pdm.s.Apic.pfnLocalInterruptR0);
2666 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pApicReg->pszLocalInterruptR0, rc));
2667 }
2668 if (RT_FAILURE(rc))
2669 {
2670 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2671 return rc;
2672 }
2673 pVM->pdm.s.Apic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
2674 Assert(pVM->pdm.s.Apic.pDevInsR0);
2675 }
2676 else
2677 {
2678 pVM->pdm.s.Apic.pfnGetInterruptR0 = 0;
2679 pVM->pdm.s.Apic.pfnHasPendingIrqR0 = 0;
2680 pVM->pdm.s.Apic.pfnSetBaseR0 = 0;
2681 pVM->pdm.s.Apic.pfnGetBaseR0 = 0;
2682 pVM->pdm.s.Apic.pfnSetTPRR0 = 0;
2683 pVM->pdm.s.Apic.pfnGetTPRR0 = 0;
2684 pVM->pdm.s.Apic.pfnWriteMSRR0 = 0;
2685 pVM->pdm.s.Apic.pfnReadMSRR0 = 0;
2686 pVM->pdm.s.Apic.pfnBusDeliverR0 = 0;
2687 pVM->pdm.s.Apic.pfnLocalInterruptR0 = 0;
2688 pVM->pdm.s.Apic.pDevInsR0 = 0;
2689 }
2690
2691 /*
2692 * Initialize the HC bits.
2693 */
2694 pVM->pdm.s.Apic.pDevInsR3 = pDevIns;
2695 pVM->pdm.s.Apic.pfnGetInterruptR3 = pApicReg->pfnGetInterruptR3;
2696 pVM->pdm.s.Apic.pfnHasPendingIrqR3 = pApicReg->pfnHasPendingIrqR3;
2697 pVM->pdm.s.Apic.pfnSetBaseR3 = pApicReg->pfnSetBaseR3;
2698 pVM->pdm.s.Apic.pfnGetBaseR3 = pApicReg->pfnGetBaseR3;
2699 pVM->pdm.s.Apic.pfnSetTPRR3 = pApicReg->pfnSetTPRR3;
2700 pVM->pdm.s.Apic.pfnGetTPRR3 = pApicReg->pfnGetTPRR3;
2701 pVM->pdm.s.Apic.pfnWriteMSRR3 = pApicReg->pfnWriteMSRR3;
2702 pVM->pdm.s.Apic.pfnReadMSRR3 = pApicReg->pfnReadMSRR3;
2703 pVM->pdm.s.Apic.pfnBusDeliverR3 = pApicReg->pfnBusDeliverR3;
2704 pVM->pdm.s.Apic.pfnLocalInterruptR3 = pApicReg->pfnLocalInterruptR3;
2705 Log(("PDM: Registered APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
2706
2707 /* set the helper pointer and return. */
2708 *ppApicHlpR3 = &g_pdmR3DevApicHlp;
2709 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
2710 return VINF_SUCCESS;
2711}
2712
2713
2714/** @interface_method_impl{PDMDEVHLPR3,pfnIOAPICRegister} */
2715static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
2716{
2717 PDMDEV_ASSERT_DEVINS(pDevIns);
2718 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2719 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppIoApicHlpR3=%p\n",
2720 pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqR3,
2721 pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqR0, pIoApicReg->pszSetIrqR0, ppIoApicHlpR3));
2722
2723 /*
2724 * Validate input.
2725 */
2726 if (pIoApicReg->u32Version != PDM_IOAPICREG_VERSION)
2727 {
2728 AssertMsgFailed(("u32Version=%#x expected %#x\n", pIoApicReg->u32Version, PDM_IOAPICREG_VERSION));
2729 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2730 return VERR_INVALID_PARAMETER;
2731 }
2732 if (!pIoApicReg->pfnSetIrqR3 || !pIoApicReg->pfnSendMsiR3)
2733 {
2734 Assert(pIoApicReg->pfnSetIrqR3);
2735 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (R3 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2736 return VERR_INVALID_PARAMETER;
2737 }
2738 if ( pIoApicReg->pszSetIrqRC
2739 && !VALID_PTR(pIoApicReg->pszSetIrqRC))
2740 {
2741 Assert(VALID_PTR(pIoApicReg->pszSetIrqRC));
2742 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2743 return VERR_INVALID_PARAMETER;
2744 }
2745 if ( pIoApicReg->pszSendMsiRC
2746 && !VALID_PTR(pIoApicReg->pszSendMsiRC))
2747 {
2748 Assert(VALID_PTR(pIoApicReg->pszSendMsiRC));
2749 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2750 return VERR_INVALID_PARAMETER;
2751 }
2752 if ( pIoApicReg->pszSetIrqR0
2753 && !VALID_PTR(pIoApicReg->pszSetIrqR0))
2754 {
2755 Assert(VALID_PTR(pIoApicReg->pszSetIrqR0));
2756 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2757 return VERR_INVALID_PARAMETER;
2758 }
2759 if ( pIoApicReg->pszSendMsiR0
2760 && !VALID_PTR(pIoApicReg->pszSendMsiR0))
2761 {
2762 Assert(VALID_PTR(pIoApicReg->pszSendMsiR0));
2763 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2764 return VERR_INVALID_PARAMETER;
2765 }
2766 if (!ppIoApicHlpR3)
2767 {
2768 Assert(ppIoApicHlpR3);
2769 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (ppApicHlp)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2770 return VERR_INVALID_PARAMETER;
2771 }
2772
2773 /*
2774 * The I/O APIC requires the APIC to be present (hacks++).
2775 * If the I/O APIC does GC stuff so must the APIC.
2776 */
2777 PVM pVM = pDevIns->Internal.s.pVMR3;
2778 if (!pVM->pdm.s.Apic.pDevInsR3)
2779 {
2780 AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
2781 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (no APIC)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2782 return VERR_INVALID_PARAMETER;
2783 }
2784 if ( pIoApicReg->pszSetIrqRC
2785 && !pVM->pdm.s.Apic.pDevInsRC)
2786 {
2787 AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
2788 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (no GC APIC)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2789 return VERR_INVALID_PARAMETER;
2790 }
2791
2792 /*
2793 * Only one I/O APIC device.
2794 */
2795 if (pVM->pdm.s.IoApic.pDevInsR3)
2796 {
2797 AssertMsgFailed(("Only one ioapic device is supported!\n"));
2798 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (only one)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2799 return VERR_INVALID_PARAMETER;
2800 }
2801
2802 /*
2803 * Resolve & initialize the GC bits.
2804 */
2805 if (pIoApicReg->pszSetIrqRC)
2806 {
2807 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSetIrqRC, &pVM->pdm.s.IoApic.pfnSetIrqRC);
2808 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pIoApicReg->pszSetIrqRC, rc));
2809 if (RT_FAILURE(rc))
2810 {
2811 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2812 return rc;
2813 }
2814 pVM->pdm.s.IoApic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
2815 }
2816 else
2817 {
2818 pVM->pdm.s.IoApic.pDevInsRC = 0;
2819 pVM->pdm.s.IoApic.pfnSetIrqRC = 0;
2820 }
2821
2822 if (pIoApicReg->pszSendMsiRC)
2823 {
2824 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSetIrqRC, &pVM->pdm.s.IoApic.pfnSendMsiRC);
2825 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pIoApicReg->pszSendMsiRC, rc));
2826 if (RT_FAILURE(rc))
2827 {
2828 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2829 return rc;
2830 }
2831 }
2832 else
2833 {
2834 pVM->pdm.s.IoApic.pfnSendMsiRC = 0;
2835 }
2836
2837 /*
2838 * Resolve & initialize the R0 bits.
2839 */
2840 if (pIoApicReg->pszSetIrqR0)
2841 {
2842 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSetIrqR0);
2843 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pIoApicReg->pszSetIrqR0, rc));
2844 if (RT_FAILURE(rc))
2845 {
2846 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2847 return rc;
2848 }
2849 pVM->pdm.s.IoApic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
2850 Assert(pVM->pdm.s.IoApic.pDevInsR0);
2851 }
2852 else
2853 {
2854 pVM->pdm.s.IoApic.pfnSetIrqR0 = 0;
2855 pVM->pdm.s.IoApic.pDevInsR0 = 0;
2856 }
2857
2858 if (pIoApicReg->pszSendMsiR0)
2859 {
2860 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSendMsiR0);
2861 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pIoApicReg->pszSendMsiR0, rc));
2862 if (RT_FAILURE(rc))
2863 {
2864 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2865 return rc;
2866 }
2867 }
2868 else
2869 {
2870 pVM->pdm.s.IoApic.pfnSendMsiR0 = 0;
2871 }
2872
2873
2874 /*
2875 * Initialize the R3 bits.
2876 */
2877 pVM->pdm.s.IoApic.pDevInsR3 = pDevIns;
2878 pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrqR3;
2879 pVM->pdm.s.IoApic.pfnSendMsiR3 = pIoApicReg->pfnSendMsiR3;
2880 Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
2881
2882 /* set the helper pointer and return. */
2883 *ppIoApicHlpR3 = &g_pdmR3DevIoApicHlp;
2884 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
2885 return VINF_SUCCESS;
2886}
2887
2888
2889/** @interface_method_impl{PDMDEVHLPR3,pfnHPETRegister} */
2890static DECLCALLBACK(int) pdmR3DevHlp_HPETRegister(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3)
2891{
2892 PDMDEV_ASSERT_DEVINS(pDevIns);
2893 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2894 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d:\n"));
2895
2896 /*
2897 * Validate input.
2898 */
2899 if (pHpetReg->u32Version != PDM_HPETREG_VERSION)
2900 {
2901 AssertMsgFailed(("u32Version=%#x expected %#x\n", pHpetReg->u32Version, PDM_HPETREG_VERSION));
2902 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2903 return VERR_INVALID_PARAMETER;
2904 }
2905
2906 if (!ppHpetHlpR3)
2907 {
2908 Assert(ppHpetHlpR3);
2909 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d: returns %Rrc (ppApicHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2910 return VERR_INVALID_PARAMETER;
2911 }
2912
2913 /* set the helper pointer and return. */
2914 *ppHpetHlpR3 = &g_pdmR3DevHpetHlp;
2915 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
2916 return VINF_SUCCESS;
2917}
2918
2919
2920/** @interface_method_impl{PDMDEVHLPR3,pfnPciRawRegister} */
2921static DECLCALLBACK(int) pdmR3DevHlp_PciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
2922{
2923 PDMDEV_ASSERT_DEVINS(pDevIns);
2924 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2925 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d:\n"));
2926
2927 /*
2928 * Validate input.
2929 */
2930 if (pPciRawReg->u32Version != PDM_PCIRAWREG_VERSION)
2931 {
2932 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciRawReg->u32Version, PDM_PCIRAWREG_VERSION));
2933 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2934 return VERR_INVALID_PARAMETER;
2935 }
2936
2937 if (!ppPciRawHlpR3)
2938 {
2939 Assert(ppPciRawHlpR3);
2940 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (ppApicHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2941 return VERR_INVALID_PARAMETER;
2942 }
2943
2944 /* set the helper pointer and return. */
2945 *ppPciRawHlpR3 = &g_pdmR3DevPciRawHlp;
2946 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
2947 return VINF_SUCCESS;
2948}
2949
2950
2951/** @interface_method_impl{PDMDEVHLPR3,pfnDMACRegister} */
2952static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
2953{
2954 PDMDEV_ASSERT_DEVINS(pDevIns);
2955 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2956 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",
2957 pDevIns->pReg->szName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
2958 pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
2959
2960 /*
2961 * Validate input.
2962 */
2963 if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
2964 {
2965 AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
2966 PDM_DMACREG_VERSION));
2967 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (version)\n",
2968 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2969 return VERR_INVALID_PARAMETER;
2970 }
2971 if ( !pDmacReg->pfnRun
2972 || !pDmacReg->pfnRegister
2973 || !pDmacReg->pfnReadMemory
2974 || !pDmacReg->pfnWriteMemory
2975 || !pDmacReg->pfnSetDREQ
2976 || !pDmacReg->pfnGetChannelMode)
2977 {
2978 Assert(pDmacReg->pfnRun);
2979 Assert(pDmacReg->pfnRegister);
2980 Assert(pDmacReg->pfnReadMemory);
2981 Assert(pDmacReg->pfnWriteMemory);
2982 Assert(pDmacReg->pfnSetDREQ);
2983 Assert(pDmacReg->pfnGetChannelMode);
2984 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
2985 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2986 return VERR_INVALID_PARAMETER;
2987 }
2988
2989 if (!ppDmacHlp)
2990 {
2991 Assert(ppDmacHlp);
2992 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (ppDmacHlp)\n",
2993 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2994 return VERR_INVALID_PARAMETER;
2995 }
2996
2997 /*
2998 * Only one DMA device.
2999 */
3000 PVM pVM = pDevIns->Internal.s.pVMR3;
3001 if (pVM->pdm.s.pDmac)
3002 {
3003 AssertMsgFailed(("Only one DMA device is supported!\n"));
3004 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3005 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3006 return VERR_INVALID_PARAMETER;
3007 }
3008
3009 /*
3010 * Allocate and initialize pci bus structure.
3011 */
3012 int rc = VINF_SUCCESS;
3013 PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
3014 if (pDmac)
3015 {
3016 pDmac->pDevIns = pDevIns;
3017 pDmac->Reg = *pDmacReg;
3018 pVM->pdm.s.pDmac = pDmac;
3019
3020 /* set the helper pointer. */
3021 *ppDmacHlp = &g_pdmR3DevDmacHlp;
3022 Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
3023 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3024 }
3025 else
3026 rc = VERR_NO_MEMORY;
3027
3028 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3029 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3030 return rc;
3031}
3032
3033
3034/**
3035 * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
3036 */
3037static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize)
3038{
3039 PDMDEV_ASSERT_DEVINS(pDevIns);
3040 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3041
3042 int rc = PDMR3RegisterVMMDevHeap(pDevIns->Internal.s.pVMR3, GCPhys, pvHeap, cbSize);
3043 return rc;
3044}
3045
3046
3047/**
3048 * @copydoc PDMDEVHLPR3::pfnUnregisterVMMDevHeap
3049 */
3050static DECLCALLBACK(int) pdmR3DevHlp_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
3051{
3052 PDMDEV_ASSERT_DEVINS(pDevIns);
3053 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3054
3055 int rc = PDMR3UnregisterVMMDevHeap(pDevIns->Internal.s.pVMR3, GCPhys);
3056 return rc;
3057}
3058
3059
3060/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
3061static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns)
3062{
3063 PDMDEV_ASSERT_DEVINS(pDevIns);
3064 PVM pVM = pDevIns->Internal.s.pVMR3;
3065 VM_ASSERT_EMT(pVM);
3066 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: VM_FF_RESET %d -> 1\n",
3067 pDevIns->pReg->szName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_RESET)));
3068
3069 /*
3070 * We postpone this operation because we're likely to be inside a I/O instruction
3071 * and the EIP will be updated when we return.
3072 * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
3073 */
3074 bool fHaltOnReset;
3075 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
3076 if (RT_SUCCESS(rc) && fHaltOnReset)
3077 {
3078 Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
3079 rc = VINF_EM_HALT;
3080 }
3081 else
3082 {
3083 VM_FF_SET(pVM, VM_FF_RESET);
3084 rc = VINF_EM_RESET;
3085 }
3086
3087 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3088 return rc;
3089}
3090
3091
3092/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
3093static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
3094{
3095 int rc;
3096 PDMDEV_ASSERT_DEVINS(pDevIns);
3097 PVM pVM = pDevIns->Internal.s.pVMR3;
3098 VM_ASSERT_EMT(pVM);
3099 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
3100 pDevIns->pReg->szName, pDevIns->iInstance));
3101
3102 /** @todo Always take the SMP path - fewer code paths. */
3103 if (pVM->cCpus > 1)
3104 {
3105 /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
3106 rc = VMR3ReqCallNoWaitU(pVM->pUVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3Suspend, 1, pVM);
3107 AssertRC(rc);
3108 rc = VINF_EM_SUSPEND;
3109 }
3110 else
3111 rc = VMR3Suspend(pVM);
3112
3113 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3114 return rc;
3115}
3116
3117
3118/**
3119 * Worker for pdmR3DevHlp_VMSuspendSaveAndPowerOff that is invoked via a queued
3120 * EMT request to avoid deadlocks.
3121 *
3122 * @returns VBox status code fit for scheduling.
3123 * @param pVM The VM handle.
3124 * @param pDevIns The device that triggered this action.
3125 */
3126static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker(PVM pVM, PPDMDEVINS pDevIns)
3127{
3128 /*
3129 * Suspend the VM first then do the saving.
3130 */
3131 int rc = VMR3Suspend(pVM);
3132 if (RT_SUCCESS(rc))
3133 {
3134 PUVM pUVM = pVM->pUVM;
3135 rc = pUVM->pVmm2UserMethods->pfnSaveState(pVM->pUVM->pVmm2UserMethods, pUVM);
3136
3137 /*
3138 * On success, power off the VM, on failure we'll leave it suspended.
3139 */
3140 if (RT_SUCCESS(rc))
3141 {
3142 rc = VMR3PowerOff(pVM);
3143 if (RT_FAILURE(rc))
3144 LogRel(("%s/SSP: VMR3PowerOff failed: %Rrc\n", pDevIns->pReg->szName, rc));
3145 }
3146 else
3147 LogRel(("%s/SSP: pfnSaveState failed: %Rrc\n", pDevIns->pReg->szName, rc));
3148 }
3149 else
3150 LogRel(("%s/SSP: Suspend failed: %Rrc\n", pDevIns->pReg->szName, rc));
3151 return rc;
3152}
3153
3154
3155/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
3156static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
3157{
3158 PDMDEV_ASSERT_DEVINS(pDevIns);
3159 PVM pVM = pDevIns->Internal.s.pVMR3;
3160 VM_ASSERT_EMT(pVM);
3161 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d:\n",
3162 pDevIns->pReg->szName, pDevIns->iInstance));
3163
3164 int rc;
3165 if ( pVM->pUVM->pVmm2UserMethods
3166 && pVM->pUVM->pVmm2UserMethods->pfnSaveState)
3167 {
3168 rc = VMR3ReqCallNoWaitU(pVM->pUVM, VMCPUID_ANY_QUEUE, (PFNRT)pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker, 2, pVM, pDevIns);
3169 if (RT_SUCCESS(rc))
3170 {
3171 LogRel(("%s: Suspending, Saving and Powering Off the VM\n", pDevIns->pReg->szName));
3172 rc = VINF_EM_SUSPEND;
3173 }
3174 }
3175 else
3176 rc = VERR_NOT_SUPPORTED;
3177
3178 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3179 return rc;
3180}
3181
3182
3183/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
3184static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
3185{
3186 int rc;
3187 PDMDEV_ASSERT_DEVINS(pDevIns);
3188 PVM pVM = pDevIns->Internal.s.pVMR3;
3189 VM_ASSERT_EMT(pVM);
3190 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
3191 pDevIns->pReg->szName, pDevIns->iInstance));
3192
3193 /** @todo Always take the SMP path - fewer code paths. */
3194 if (pVM->cCpus > 1)
3195 {
3196 /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
3197 rc = VMR3ReqCallNoWaitU(pVM->pUVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3PowerOff, 1, pVM);
3198 AssertRC(rc);
3199 /* Set the VCPU state to stopped here as well to make sure no
3200 * inconsistency with the EM state occurs.
3201 */
3202 VMCPU_SET_STATE(VMMGetCpu(pVM), VMCPUSTATE_STOPPED);
3203 rc = VINF_EM_OFF;
3204 }
3205 else
3206 rc = VMR3PowerOff(pVM);
3207
3208 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3209 return rc;
3210}
3211
3212
3213/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
3214static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
3215{
3216 PDMDEV_ASSERT_DEVINS(pDevIns);
3217 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3218
3219 bool fRc = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pVMR3));
3220
3221 LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pReg->szName, pDevIns->iInstance, fRc));
3222 return fRc;
3223}
3224
3225
3226/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
3227static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
3228{
3229 PDMDEV_ASSERT_DEVINS(pDevIns);
3230 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3231 LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, fEnable));
3232 PGMR3PhysSetA20(VMMGetCpu(pDevIns->Internal.s.pVMR3), fEnable);
3233}
3234
3235
3236/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
3237static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
3238 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
3239{
3240 PDMDEV_ASSERT_DEVINS(pDevIns);
3241 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3242
3243 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
3244 pDevIns->pReg->szName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
3245 AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
3246
3247 CPUMGetGuestCpuId(VMMGetCpu(pDevIns->Internal.s.pVMR3), iLeaf, pEax, pEbx, pEcx, pEdx);
3248
3249 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
3250 pDevIns->pReg->szName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
3251}
3252
3253
3254/**
3255 * The device helper structure for trusted devices.
3256 */
3257const PDMDEVHLPR3 g_pdmR3DevHlpTrusted =
3258{
3259 PDM_DEVHLPR3_VERSION,
3260 pdmR3DevHlp_IOPortRegister,
3261 pdmR3DevHlp_IOPortRegisterRC,
3262 pdmR3DevHlp_IOPortRegisterR0,
3263 pdmR3DevHlp_IOPortDeregister,
3264 pdmR3DevHlp_MMIORegister,
3265 pdmR3DevHlp_MMIORegisterRC,
3266 pdmR3DevHlp_MMIORegisterR0,
3267 pdmR3DevHlp_MMIODeregister,
3268 pdmR3DevHlp_MMIO2Register,
3269 pdmR3DevHlp_MMIO2Deregister,
3270 pdmR3DevHlp_MMIO2Map,
3271 pdmR3DevHlp_MMIO2Unmap,
3272 pdmR3DevHlp_MMHyperMapMMIO2,
3273 pdmR3DevHlp_MMIO2MapKernel,
3274 pdmR3DevHlp_ROMRegister,
3275 pdmR3DevHlp_ROMProtectShadow,
3276 pdmR3DevHlp_SSMRegister,
3277 pdmR3DevHlp_TMTimerCreate,
3278 pdmR3DevHlp_TMUtcNow,
3279 pdmR3DevHlp_PhysRead,
3280 pdmR3DevHlp_PhysWrite,
3281 pdmR3DevHlp_PhysGCPhys2CCPtr,
3282 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
3283 pdmR3DevHlp_PhysReleasePageMappingLock,
3284 pdmR3DevHlp_PhysReadGCVirt,
3285 pdmR3DevHlp_PhysWriteGCVirt,
3286 pdmR3DevHlp_PhysGCPtr2GCPhys,
3287 pdmR3DevHlp_MMHeapAlloc,
3288 pdmR3DevHlp_MMHeapAllocZ,
3289 pdmR3DevHlp_MMHeapFree,
3290 pdmR3DevHlp_VMState,
3291 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
3292 pdmR3DevHlp_VMSetError,
3293 pdmR3DevHlp_VMSetErrorV,
3294 pdmR3DevHlp_VMSetRuntimeError,
3295 pdmR3DevHlp_VMSetRuntimeErrorV,
3296 pdmR3DevHlp_DBGFStopV,
3297 pdmR3DevHlp_DBGFInfoRegister,
3298 pdmR3DevHlp_DBGFTraceBuf,
3299 pdmR3DevHlp_STAMRegister,
3300 pdmR3DevHlp_STAMRegisterF,
3301 pdmR3DevHlp_STAMRegisterV,
3302 pdmR3DevHlp_PCIRegister,
3303 pdmR3DevHlp_PCIRegisterMsi,
3304 pdmR3DevHlp_PCIIORegionRegister,
3305 pdmR3DevHlp_PCISetConfigCallbacks,
3306 pdmR3DevHlp_PCISetIrq,
3307 pdmR3DevHlp_PCISetIrqNoWait,
3308 pdmR3DevHlp_ISASetIrq,
3309 pdmR3DevHlp_ISASetIrqNoWait,
3310 pdmR3DevHlp_DriverAttach,
3311 pdmR3DevHlp_QueueCreate,
3312 pdmR3DevHlp_CritSectInit,
3313 pdmR3DevHlp_CritSectGetNop,
3314 pdmR3DevHlp_CritSectGetNopR0,
3315 pdmR3DevHlp_CritSectGetNopRC,
3316 pdmR3DevHlp_SetDeviceCritSect,
3317 pdmR3DevHlp_ThreadCreate,
3318 pdmR3DevHlp_SetAsyncNotification,
3319 pdmR3DevHlp_AsyncNotificationCompleted,
3320 pdmR3DevHlp_RTCRegister,
3321 pdmR3DevHlp_PCIBusRegister,
3322 pdmR3DevHlp_PICRegister,
3323 pdmR3DevHlp_APICRegister,
3324 pdmR3DevHlp_IOAPICRegister,
3325 pdmR3DevHlp_HPETRegister,
3326 pdmR3DevHlp_PciRawRegister,
3327 pdmR3DevHlp_DMACRegister,
3328 pdmR3DevHlp_DMARegister,
3329 pdmR3DevHlp_DMAReadMemory,
3330 pdmR3DevHlp_DMAWriteMemory,
3331 pdmR3DevHlp_DMASetDREQ,
3332 pdmR3DevHlp_DMAGetChannelMode,
3333 pdmR3DevHlp_DMASchedule,
3334 pdmR3DevHlp_CMOSWrite,
3335 pdmR3DevHlp_CMOSRead,
3336 pdmR3DevHlp_AssertEMT,
3337 pdmR3DevHlp_AssertOther,
3338 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
3339 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
3340 pdmR3DevHlp_CallR0,
3341 0,
3342 0,
3343 0,
3344 0,
3345 0,
3346 0,
3347 0,
3348 0,
3349 0,
3350 0,
3351 pdmR3DevHlp_GetVM,
3352 pdmR3DevHlp_GetVMCPU,
3353 pdmR3DevHlp_RegisterVMMDevHeap,
3354 pdmR3DevHlp_UnregisterVMMDevHeap,
3355 pdmR3DevHlp_VMReset,
3356 pdmR3DevHlp_VMSuspend,
3357 pdmR3DevHlp_VMSuspendSaveAndPowerOff,
3358 pdmR3DevHlp_VMPowerOff,
3359 pdmR3DevHlp_A20IsEnabled,
3360 pdmR3DevHlp_A20Set,
3361 pdmR3DevHlp_GetCpuId,
3362 pdmR3DevHlp_TMTimeVirtGet,
3363 pdmR3DevHlp_TMTimeVirtGetFreq,
3364 pdmR3DevHlp_TMTimeVirtGetNano,
3365 PDM_DEVHLPR3_VERSION /* the end */
3366};
3367
3368
3369
3370
3371/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
3372static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
3373{
3374 PDMDEV_ASSERT_DEVINS(pDevIns);
3375 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
3376 return NULL;
3377}
3378
3379
3380/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
3381static DECLCALLBACK(PVMCPU) pdmR3DevHlp_Untrusted_GetVMCPU(PPDMDEVINS pDevIns)
3382{
3383 PDMDEV_ASSERT_DEVINS(pDevIns);
3384 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
3385 return NULL;
3386}
3387
3388
3389/** @interface_method_impl{PDMDEVHLPR3,pfnRegisterVMMDevHeap} */
3390static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize)
3391{
3392 PDMDEV_ASSERT_DEVINS(pDevIns);
3393 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
3394 return VERR_ACCESS_DENIED;
3395}
3396
3397
3398/** @interface_method_impl{PDMDEVHLPR3,pfnUnregisterVMMDevHeap} */
3399static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
3400{
3401 PDMDEV_ASSERT_DEVINS(pDevIns);
3402 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
3403 return VERR_ACCESS_DENIED;
3404}
3405
3406
3407/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
3408static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns)
3409{
3410 PDMDEV_ASSERT_DEVINS(pDevIns);
3411 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
3412 return VERR_ACCESS_DENIED;
3413}
3414
3415
3416/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
3417static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
3418{
3419 PDMDEV_ASSERT_DEVINS(pDevIns);
3420 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
3421 return VERR_ACCESS_DENIED;
3422}
3423
3424
3425/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
3426static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
3427{
3428 PDMDEV_ASSERT_DEVINS(pDevIns);
3429 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
3430 return VERR_ACCESS_DENIED;
3431}
3432
3433
3434/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
3435static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
3436{
3437 PDMDEV_ASSERT_DEVINS(pDevIns);
3438 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
3439 return VERR_ACCESS_DENIED;
3440}
3441
3442
3443/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
3444static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
3445{
3446 PDMDEV_ASSERT_DEVINS(pDevIns);
3447 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
3448 return false;
3449}
3450
3451
3452/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
3453static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
3454{
3455 PDMDEV_ASSERT_DEVINS(pDevIns);
3456 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
3457 NOREF(fEnable);
3458}
3459
3460
3461/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
3462static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
3463 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
3464{
3465 PDMDEV_ASSERT_DEVINS(pDevIns);
3466 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
3467}
3468
3469
3470/**
3471 * The device helper structure for non-trusted devices.
3472 */
3473const PDMDEVHLPR3 g_pdmR3DevHlpUnTrusted =
3474{
3475 PDM_DEVHLPR3_VERSION,
3476 pdmR3DevHlp_IOPortRegister,
3477 pdmR3DevHlp_IOPortRegisterRC,
3478 pdmR3DevHlp_IOPortRegisterR0,
3479 pdmR3DevHlp_IOPortDeregister,
3480 pdmR3DevHlp_MMIORegister,
3481 pdmR3DevHlp_MMIORegisterRC,
3482 pdmR3DevHlp_MMIORegisterR0,
3483 pdmR3DevHlp_MMIODeregister,
3484 pdmR3DevHlp_MMIO2Register,
3485 pdmR3DevHlp_MMIO2Deregister,
3486 pdmR3DevHlp_MMIO2Map,
3487 pdmR3DevHlp_MMIO2Unmap,
3488 pdmR3DevHlp_MMHyperMapMMIO2,
3489 pdmR3DevHlp_MMIO2MapKernel,
3490 pdmR3DevHlp_ROMRegister,
3491 pdmR3DevHlp_ROMProtectShadow,
3492 pdmR3DevHlp_SSMRegister,
3493 pdmR3DevHlp_TMTimerCreate,
3494 pdmR3DevHlp_TMUtcNow,
3495 pdmR3DevHlp_PhysRead,
3496 pdmR3DevHlp_PhysWrite,
3497 pdmR3DevHlp_PhysGCPhys2CCPtr,
3498 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
3499 pdmR3DevHlp_PhysReleasePageMappingLock,
3500 pdmR3DevHlp_PhysReadGCVirt,
3501 pdmR3DevHlp_PhysWriteGCVirt,
3502 pdmR3DevHlp_PhysGCPtr2GCPhys,
3503 pdmR3DevHlp_MMHeapAlloc,
3504 pdmR3DevHlp_MMHeapAllocZ,
3505 pdmR3DevHlp_MMHeapFree,
3506 pdmR3DevHlp_VMState,
3507 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
3508 pdmR3DevHlp_VMSetError,
3509 pdmR3DevHlp_VMSetErrorV,
3510 pdmR3DevHlp_VMSetRuntimeError,
3511 pdmR3DevHlp_VMSetRuntimeErrorV,
3512 pdmR3DevHlp_DBGFStopV,
3513 pdmR3DevHlp_DBGFInfoRegister,
3514 pdmR3DevHlp_DBGFTraceBuf,
3515 pdmR3DevHlp_STAMRegister,
3516 pdmR3DevHlp_STAMRegisterF,
3517 pdmR3DevHlp_STAMRegisterV,
3518 pdmR3DevHlp_PCIRegister,
3519 pdmR3DevHlp_PCIRegisterMsi,
3520 pdmR3DevHlp_PCIIORegionRegister,
3521 pdmR3DevHlp_PCISetConfigCallbacks,
3522 pdmR3DevHlp_PCISetIrq,
3523 pdmR3DevHlp_PCISetIrqNoWait,
3524 pdmR3DevHlp_ISASetIrq,
3525 pdmR3DevHlp_ISASetIrqNoWait,
3526 pdmR3DevHlp_DriverAttach,
3527 pdmR3DevHlp_QueueCreate,
3528 pdmR3DevHlp_CritSectInit,
3529 pdmR3DevHlp_CritSectGetNop,
3530 pdmR3DevHlp_CritSectGetNopR0,
3531 pdmR3DevHlp_CritSectGetNopRC,
3532 pdmR3DevHlp_SetDeviceCritSect,
3533 pdmR3DevHlp_ThreadCreate,
3534 pdmR3DevHlp_SetAsyncNotification,
3535 pdmR3DevHlp_AsyncNotificationCompleted,
3536 pdmR3DevHlp_RTCRegister,
3537 pdmR3DevHlp_PCIBusRegister,
3538 pdmR3DevHlp_PICRegister,
3539 pdmR3DevHlp_APICRegister,
3540 pdmR3DevHlp_IOAPICRegister,
3541 pdmR3DevHlp_HPETRegister,
3542 pdmR3DevHlp_PciRawRegister,
3543 pdmR3DevHlp_DMACRegister,
3544 pdmR3DevHlp_DMARegister,
3545 pdmR3DevHlp_DMAReadMemory,
3546 pdmR3DevHlp_DMAWriteMemory,
3547 pdmR3DevHlp_DMASetDREQ,
3548 pdmR3DevHlp_DMAGetChannelMode,
3549 pdmR3DevHlp_DMASchedule,
3550 pdmR3DevHlp_CMOSWrite,
3551 pdmR3DevHlp_CMOSRead,
3552 pdmR3DevHlp_AssertEMT,
3553 pdmR3DevHlp_AssertOther,
3554 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
3555 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
3556 pdmR3DevHlp_CallR0,
3557 0,
3558 0,
3559 0,
3560 0,
3561 0,
3562 0,
3563 0,
3564 0,
3565 0,
3566 0,
3567 pdmR3DevHlp_Untrusted_GetVM,
3568 pdmR3DevHlp_Untrusted_GetVMCPU,
3569 pdmR3DevHlp_Untrusted_RegisterVMMDevHeap,
3570 pdmR3DevHlp_Untrusted_UnregisterVMMDevHeap,
3571 pdmR3DevHlp_Untrusted_VMReset,
3572 pdmR3DevHlp_Untrusted_VMSuspend,
3573 pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff,
3574 pdmR3DevHlp_Untrusted_VMPowerOff,
3575 pdmR3DevHlp_Untrusted_A20IsEnabled,
3576 pdmR3DevHlp_Untrusted_A20Set,
3577 pdmR3DevHlp_Untrusted_GetCpuId,
3578 pdmR3DevHlp_TMTimeVirtGet,
3579 pdmR3DevHlp_TMTimeVirtGetFreq,
3580 pdmR3DevHlp_TMTimeVirtGetNano,
3581 PDM_DEVHLPR3_VERSION /* the end */
3582};
3583
3584
3585
3586/**
3587 * Queue consumer callback for internal component.
3588 *
3589 * @returns Success indicator.
3590 * If false the item will not be removed and the flushing will stop.
3591 * @param pVM The VM handle.
3592 * @param pItem The item to consume. Upon return this item will be freed.
3593 */
3594DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
3595{
3596 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
3597 LogFlow(("pdmR3DevHlpQueueConsumer: enmOp=%d pDevIns=%p\n", pTask->enmOp, pTask->pDevInsR3));
3598 switch (pTask->enmOp)
3599 {
3600 case PDMDEVHLPTASKOP_ISA_SET_IRQ:
3601 PDMIsaSetIrq(pVM, pTask->u.SetIRQ.iIrq, pTask->u.SetIRQ.iLevel);
3602 break;
3603
3604 case PDMDEVHLPTASKOP_PCI_SET_IRQ:
3605 pdmR3DevHlp_PCISetIrq(pTask->pDevInsR3, pTask->u.SetIRQ.iIrq, pTask->u.SetIRQ.iLevel);
3606 break;
3607
3608 case PDMDEVHLPTASKOP_IOAPIC_SET_IRQ:
3609 PDMIoApicSetIrq(pVM, pTask->u.SetIRQ.iIrq, pTask->u.SetIRQ.iLevel);
3610 break;
3611
3612 default:
3613 AssertReleaseMsgFailed(("Invalid operation %d\n", pTask->enmOp));
3614 break;
3615 }
3616 return true;
3617}
3618
3619/** @} */
3620
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