VirtualBox

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

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

VMM,Devices,Main: Implemented soft/warm reset for shutdown status codes 05h, 09h and 0Ah.

This is a shot at adjusting our VM reset handling to handle the ancient way of
getting a 286 out of protected mode and back to real mode. Our exiting reset
code (XXXR3Reset, PDMDEVREG::pfnReset, and so on) is doing a cold reset of the
system and then some additional device & memory initialization that the firmware
is usually responsible for doing. When the guest triggers a reset via the
keyboard controller, system control port A, CPU triple fault, and possibly ACPI,
only the CPU is supposed to be reset. The BIOS would then decide whether memory
and devices needed resetting as well, or if the resetter justed wanted to get out
protected mode and resume executing some real mode code pointed to by 467h.

  • New states SOFT_RESETTING and SOFT_RESETTING_LS. The latter returns to RUNNING_LS, not SUSPENDED_LS like for hard reset.
  • Added a firmware interface so the VMM/PDM can ask it whether we're supposed to do a hard reset or a soft(/warm) one.
  • Implemented firmware interface for the PC BIOS (but not EFI). It indicates soft(/warm) reset when CMOS[0xf] is 5, 9 or 10.
  • Moved the CMOS[0xf] resetting from the RTC device to the PC BIOS since it's firmware thing, not RTC.
  • Added a flag parameter to PDMDevHlpVMReset for specifying the source of the reset operation. One class of sources (GIM) will always trigger hard resets, whereas the others will check with the firmware first.
  • Added PDMR3GetResetInfo for query the flags passed to PDMDevHlpVMReset and for asking the firmware whether it's a hard or soft reset. The latter, however, is only done if only CPU 0 is active. Systems with more than one CPU in a state other than EMSTATE_WAIT_SIPI status will always be hard reset.
  • Added internal VMR3ResetFF and VMR3ResetTripleFault APIs for handling the VM_FF_RESET and VINF_EM_TRIPLE_FAULT conditions.
  • Added PMDR3ResetSoft and had it call pfnSoftReset (which is now defined).

Warning! Major PDM_DEVHLPR3_VERSION change, minor PDM_DEVREG_VERSION change.

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