VirtualBox

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

Last change on this file since 55966 was 55899, checked in by vboxsync, 10 years ago

PGM: Added an access origin to memory read & write calls that respects handlers. This will later be passed to the access handler, so that things like the page pool (and potentially others) can query IEM about instruction details when needed.

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