VirtualBox

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

Last change on this file since 81031 was 81031, checked in by vboxsync, 5 years ago

PDM,Devices: Moving the PDMPCIDEV structures into the PDMDEVINS allocation. Preps for extending the config space to 4KB. bugref:9218

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 189.5 KB
Line 
1/* $Id: PDMDevHlp.cpp 81031 2019-09-26 19:26:33Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, Device Helpers.
4 */
5
6/*
7 * Copyright (C) 2006-2019 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#define PDMPCIDEV_INCLUDE_PRIVATE /* Hack to get pdmpcidevint.h included at the right point. */
24#include "PDMInternal.h"
25#include <VBox/vmm/pdm.h>
26#include <VBox/vmm/mm.h>
27#include <VBox/vmm/hm.h>
28#include <VBox/vmm/pgm.h>
29#include <VBox/vmm/iom.h>
30#ifdef VBOX_WITH_REM
31# include <VBox/vmm/rem.h>
32#endif
33#include <VBox/vmm/dbgf.h>
34#include <VBox/vmm/ssm.h>
35#include <VBox/vmm/vmapi.h>
36#include <VBox/vmm/vmm.h>
37#include <VBox/vmm/vmcc.h>
38
39#include <VBox/version.h>
40#include <VBox/log.h>
41#include <VBox/err.h>
42#include <iprt/asm.h>
43#include <iprt/assert.h>
44#include <iprt/ctype.h>
45#include <iprt/string.h>
46#include <iprt/thread.h>
47
48#include "dtrace/VBoxVMM.h"
49#include "PDMInline.h"
50
51
52/*********************************************************************************************************************************
53* Defined Constants And Macros *
54*********************************************************************************************************************************/
55/** @def PDM_DEVHLP_DEADLOCK_DETECTION
56 * Define this to enable the deadlock detection when accessing physical memory.
57 */
58#if /*defined(DEBUG_bird) ||*/ defined(DOXYGEN_RUNNING)
59# define PDM_DEVHLP_DEADLOCK_DETECTION /**< @todo enable DevHlp deadlock detection! */
60#endif
61
62
63
64/**
65 * Wrapper around PDMR3LdrGetSymbolRCLazy.
66 */
67DECLINLINE(int) pdmR3DevGetSymbolRCLazy(PPDMDEVINS pDevIns, const char *pszSymbol, PRTRCPTR ppvValue)
68{
69 PVM pVM = pDevIns->Internal.s.pVMR3;
70 if (!VM_IS_RAW_MODE_ENABLED(pVM))
71 {
72 *ppvValue = NIL_RTRCPTR;
73 return VINF_SUCCESS;
74 }
75 return PDMR3LdrGetSymbolRCLazy(pVM,
76 pDevIns->Internal.s.pDevR3->pReg->pszRCMod,
77 pDevIns->Internal.s.pDevR3->pszRCSearchPath,
78 pszSymbol, ppvValue);
79}
80
81
82/**
83 * Wrapper around PDMR3LdrGetSymbolR0Lazy.
84 */
85DECLINLINE(int) pdmR3DevGetSymbolR0Lazy(PPDMDEVINS pDevIns, const char *pszSymbol, PRTR0PTR ppvValue)
86{
87 return PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3,
88 pDevIns->Internal.s.pDevR3->pReg->pszR0Mod,
89 pDevIns->Internal.s.pDevR3->pszR0SearchPath,
90 pszSymbol, ppvValue);
91}
92
93
94/** @name R3 DevHlp
95 * @{
96 */
97
98
99/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortCreateEx} */
100static DECLCALLBACK(int) pdmR3DevHlp_IoPortCreateEx(PPDMDEVINS pDevIns, RTIOPORT cPorts, uint32_t fFlags, PPDMPCIDEV pPciDev,
101 uint32_t iPciRegion, PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
102 PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr, RTR3PTR pvUser,
103 const char *pszDesc, PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts)
104{
105 PDMDEV_ASSERT_DEVINS(pDevIns);
106 LogFlow(("pdmR3DevHlp_IoPortCreateEx: caller='%s'/%d: cPorts=%#x fFlags=%#x pPciDev=%p iPciRegion=%#x pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pvUser=%p pszDesc=%p:{%s} paExtDescs=%p phIoPorts=%p\n",
107 pDevIns->pReg->szName, pDevIns->iInstance, cPorts, fFlags, pPciDev, iPciRegion, pfnOut, pfnIn, pfnOutStr, pfnInStr,
108 pvUser, pszDesc, pszDesc, paExtDescs, phIoPorts));
109 PVM pVM = pDevIns->Internal.s.pVMR3;
110 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
111 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
112
113 int rc = IOMR3IoPortCreate(pVM, pDevIns, cPorts, fFlags, pPciDev, iPciRegion,
114 pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser, pszDesc, paExtDescs, phIoPorts);
115
116 LogFlow(("pdmR3DevHlp_IoPortCreateEx: caller='%s'/%d: returns %Rrc (*phIoPorts=%#x)\n",
117 pDevIns->pReg->szName, pDevIns->iInstance, rc, *phIoPorts));
118 return rc;
119}
120
121
122/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortMap} */
123static DECLCALLBACK(int) pdmR3DevHlp_IoPortMap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts, RTIOPORT Port)
124{
125 PDMDEV_ASSERT_DEVINS(pDevIns);
126 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x Port=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts, Port));
127 PVM pVM = pDevIns->Internal.s.pVMR3;
128 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
129
130 int rc = IOMR3IoPortMap(pVM, pDevIns, hIoPorts, Port);
131
132 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
133 return rc;
134}
135
136
137/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortUnmap} */
138static DECLCALLBACK(int) pdmR3DevHlp_IoPortUnmap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts)
139{
140 PDMDEV_ASSERT_DEVINS(pDevIns);
141 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts));
142 PVM pVM = pDevIns->Internal.s.pVMR3;
143 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
144
145 int rc = IOMR3IoPortUnmap(pVM, pDevIns, hIoPorts);
146
147 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
148 return rc;
149}
150
151/** @interface_method_impl{PDMDEVHLPR3,pfnIOPortRegister} */
152static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,
153 PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc)
154{
155 PDMDEV_ASSERT_DEVINS(pDevIns);
156 LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pszDesc=%p:{%s}\n", pDevIns->pReg->szName, pDevIns->iInstance,
157 Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc, pszDesc));
158 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
159
160#if 0 /** @todo needs a real string cache for this */
161 if (pDevIns->iInstance > 0)
162 {
163 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
164 if (pszDesc2)
165 pszDesc = pszDesc2;
166 }
167#endif
168
169 int rc = IOMR3IOPortRegisterR3(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser,
170 pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc);
171
172 LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
173 return rc;
174}
175
176
177/** @interface_method_impl{PDMDEVHLPR3,pfnIOPortRegisterRC} */
178static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterRC(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTRCPTR pvUser,
179 const char *pszOut, const char *pszIn,
180 const char *pszOutStr, const char *pszInStr, const char *pszDesc)
181{
182 PDMDEV_ASSERT_DEVINS(pDevIns);
183 Assert(pDevIns->pReg->pszRCMod[0]);
184 Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC);
185 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,
186 Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
187
188#if 0
189 /*
190 * Resolve the functions (one of the can be NULL).
191 */
192 PVM pVM = pDevIns->Internal.s.pVMR3;
193 VM_ASSERT_EMT(pVM);
194 int rc = VINF_SUCCESS;
195 if ( pDevIns->pReg->pszRCMod[0]
196 && (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
197 && VM_IS_RAW_MODE_ENABLED(pVM))
198 {
199 RTRCPTR RCPtrIn = NIL_RTRCPTR;
200 if (pszIn)
201 {
202 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszIn, &RCPtrIn);
203 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pReg->pszRCMod, pszIn));
204 }
205 RTRCPTR RCPtrOut = NIL_RTRCPTR;
206 if (pszOut && RT_SUCCESS(rc))
207 {
208 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszOut, &RCPtrOut);
209 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pReg->pszRCMod, pszOut));
210 }
211 RTRCPTR RCPtrInStr = NIL_RTRCPTR;
212 if (pszInStr && RT_SUCCESS(rc))
213 {
214 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszInStr, &RCPtrInStr);
215 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pReg->pszRCMod, pszInStr));
216 }
217 RTRCPTR RCPtrOutStr = NIL_RTRCPTR;
218 if (pszOutStr && RT_SUCCESS(rc))
219 {
220 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszOutStr, &RCPtrOutStr);
221 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pReg->pszRCMod, pszOutStr));
222 }
223
224 if (RT_SUCCESS(rc))
225 {
226#if 0 /** @todo needs a real string cache for this */
227 if (pDevIns->iInstance > 0)
228 {
229 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
230 if (pszDesc2)
231 pszDesc = pszDesc2;
232 }
233#endif
234
235 rc = IOMR3IOPortRegisterRC(pVM, pDevIns, Port, cPorts, pvUser, RCPtrOut, RCPtrIn, RCPtrOutStr, RCPtrInStr, pszDesc);
236 }
237 }
238 else if (VM_IS_RAW_MODE_ENABLED(pVM))
239 {
240 AssertMsgFailed(("No RC module for this driver!\n"));
241 rc = VERR_INVALID_PARAMETER;
242 }
243#else
244 RT_NOREF(pDevIns, Port, cPorts, pvUser, pszOut, pszIn, pszOutStr, pszInStr, pszDesc);
245 int rc = VINF_SUCCESS;
246#endif
247
248 LogFlow(("pdmR3DevHlp_IOPortRegisterRC: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
249 return rc;
250}
251
252
253/** @interface_method_impl{PDMDEVHLPR3,pfnIOPortRegisterR0} */
254static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTR0PTR pvUser,
255 const char *pszOut, const char *pszIn,
256 const char *pszOutStr, const char *pszInStr, const char *pszDesc)
257{
258 PDMDEV_ASSERT_DEVINS(pDevIns);
259 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
260 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,
261 Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
262
263 /*
264 * Resolve the functions (one of the can be NULL).
265 */
266 int rc = VINF_SUCCESS;
267 if ( pDevIns->pReg->pszR0Mod[0]
268 && (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0))
269 {
270 R0PTRTYPE(PFNIOMIOPORTIN) pfnR0PtrIn = 0;
271 if (pszIn)
272 {
273 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszIn, &pfnR0PtrIn);
274 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pReg->pszR0Mod, pszIn));
275 }
276 R0PTRTYPE(PFNIOMIOPORTOUT) pfnR0PtrOut = 0;
277 if (pszOut && RT_SUCCESS(rc))
278 {
279 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszOut, &pfnR0PtrOut);
280 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pReg->pszR0Mod, pszOut));
281 }
282 R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnR0PtrInStr = 0;
283 if (pszInStr && RT_SUCCESS(rc))
284 {
285 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszInStr, &pfnR0PtrInStr);
286 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pReg->pszR0Mod, pszInStr));
287 }
288 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnR0PtrOutStr = 0;
289 if (pszOutStr && RT_SUCCESS(rc))
290 {
291 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszOutStr, &pfnR0PtrOutStr);
292 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pReg->pszR0Mod, pszOutStr));
293 }
294
295 if (RT_SUCCESS(rc))
296 {
297#if 0 /** @todo needs a real string cache for this */
298 if (pDevIns->iInstance > 0)
299 {
300 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
301 if (pszDesc2)
302 pszDesc = pszDesc2;
303 }
304#endif
305
306 rc = IOMR3IOPortRegisterR0(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, pfnR0PtrOut, pfnR0PtrIn, pfnR0PtrOutStr, pfnR0PtrInStr, pszDesc);
307 }
308 }
309 else
310 {
311 AssertMsgFailed(("No R0 module for this driver!\n"));
312 rc = VERR_INVALID_PARAMETER;
313 }
314
315 LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
316 return rc;
317}
318
319
320/** @interface_method_impl{PDMDEVHLPR3,pfnIOPortDeregister} */
321static DECLCALLBACK(int) pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts)
322{
323 PDMDEV_ASSERT_DEVINS(pDevIns);
324 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
325 LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: Port=%#x cPorts=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance,
326 Port, cPorts));
327
328 int rc = IOMR3IOPortDeregister(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts);
329
330 LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
331 return rc;
332}
333
334
335/** @interface_method_impl{PDMDEVHLPR3,pfnMmioCreateEx} */
336static DECLCALLBACK(int) pdmR3DevHlp_MmioCreateEx(PPDMDEVINS pDevIns, RTGCPHYS cbRegion,
337 uint32_t fFlags, PPDMPCIDEV pPciDev, uint32_t iPciRegion,
338 PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
339 void *pvUser, const char *pszDesc, PIOMMMIOHANDLE phRegion)
340{
341 RT_NOREF(pDevIns, cbRegion, fFlags, pPciDev, iPciRegion, pfnWrite, pfnRead, pfnFill, pvUser, pszDesc, phRegion);
342 return VERR_NOT_IMPLEMENTED;
343}
344
345
346/** @interface_method_impl{PDMDEVHLPR3,pfnMmioMap} */
347static DECLCALLBACK(int) pdmR3DevHlp_MmioMap(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS GCPhys)
348{
349 RT_NOREF(pDevIns, hRegion, GCPhys);
350 return VERR_NOT_IMPLEMENTED;
351}
352
353
354/** @interface_method_impl{PDMDEVHLPR3,pfnMmioUnmap} */
355static DECLCALLBACK(int) pdmR3DevHlp_MmioUnmap(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)
356{
357 RT_NOREF(pDevIns, hRegion);
358 return VERR_NOT_IMPLEMENTED;
359}
360
361
362/** @interface_method_impl{PDMDEVHLPR3,pfnMmioReduce} */
363static DECLCALLBACK(int) pdmR3DevHlp_MmioReduce(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS cbRegion)
364{
365 RT_NOREF(pDevIns, hRegion, cbRegion);
366 return VERR_NOT_IMPLEMENTED;
367}
368
369
370/** @interface_method_impl{PDMDEVHLPR3,pfnMMIORegister} */
371static DECLCALLBACK(int) pdmR3DevHlp_MMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTGCPHYS cbRange, RTHCPTR pvUser,
372 PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
373 uint32_t fFlags, const char *pszDesc)
374{
375 PDMDEV_ASSERT_DEVINS(pDevIns);
376 PVM pVM = pDevIns->Internal.s.pVMR3;
377 VM_ASSERT_EMT(pVM);
378 LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: GCPhysStart=%RGp cbRange=%RGp pvUser=%p pfnWrite=%p pfnRead=%p pfnFill=%p fFlags=%#x pszDesc=%p:{%s}\n",
379 pDevIns->pReg->szName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc, fFlags, pszDesc));
380
381 if (pDevIns->iInstance > 0)
382 {
383 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
384 if (pszDesc2)
385 pszDesc = pszDesc2;
386 }
387
388 int rc = IOMR3MmioRegisterR3(pVM, pDevIns, GCPhysStart, cbRange, pvUser,
389 pfnWrite, pfnRead, pfnFill, fFlags, pszDesc);
390
391 LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
392 return rc;
393}
394
395
396/** @interface_method_impl{PDMDEVHLPR3,pfnMMIORegisterRC} */
397static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterRC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTGCPHYS cbRange, RTRCPTR pvUser,
398 const char *pszWrite, const char *pszRead, const char *pszFill)
399{
400 PDMDEV_ASSERT_DEVINS(pDevIns);
401 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
402 Assert(pDevIns->pReg->pszR0Mod[0]);
403 Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0);
404 LogFlow(("pdmR3DevHlp_MMIORegisterRC: caller='%s'/%d: GCPhysStart=%RGp cbRange=%RGp pvUser=%p pszWrite=%p:{%s} pszRead=%p:{%s} pszFill=%p:{%s}\n",
405 pDevIns->pReg->szName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill));
406
407#if 0
408 /*
409 * Resolve the functions.
410 * Not all function have to present, leave it to IOM to enforce this.
411 */
412 int rc = VINF_SUCCESS;
413 if ( pDevIns->pReg->pszRCMod[0]
414 && (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
415 && VM_IS_RAW_MODE_ENABLED(pDevIns->Internal.s.pVMR3))
416 {
417 RTRCPTR RCPtrWrite = NIL_RTRCPTR;
418 if (pszWrite)
419 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszWrite, &RCPtrWrite);
420
421 RTRCPTR RCPtrRead = NIL_RTRCPTR;
422 int rc2 = VINF_SUCCESS;
423 if (pszRead)
424 rc2 = pdmR3DevGetSymbolRCLazy(pDevIns, pszRead, &RCPtrRead);
425
426 RTRCPTR RCPtrFill = NIL_RTRCPTR;
427 int rc3 = VINF_SUCCESS;
428 if (pszFill)
429 rc3 = pdmR3DevGetSymbolRCLazy(pDevIns, pszFill, &RCPtrFill);
430
431 if (RT_SUCCESS(rc) && RT_SUCCESS(rc2) && RT_SUCCESS(rc3))
432 rc = IOMR3MmioRegisterRC(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, RCPtrWrite, RCPtrRead, RCPtrFill);
433 else
434 {
435 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszWrite)\n", pDevIns->pReg->pszRCMod, pszWrite));
436 AssertMsgRC(rc2, ("Failed to resolve %s.%s (pszRead)\n", pDevIns->pReg->pszRCMod, pszRead));
437 AssertMsgRC(rc3, ("Failed to resolve %s.%s (pszFill)\n", pDevIns->pReg->pszRCMod, pszFill));
438 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
439 rc = rc2;
440 if (RT_FAILURE(rc3) && RT_SUCCESS(rc))
441 rc = rc3;
442 }
443 }
444 else if (VM_IS_RAW_MODE_ENABLED(pDevIns->Internal.s.pVMR3))
445 {
446 AssertMsgFailed(("No RC module for this driver!\n"));
447 rc = VERR_INVALID_PARAMETER;
448 }
449#else
450 int rc = VINF_SUCCESS;
451 RT_NOREF(pDevIns, GCPhysStart, cbRange, pvUser, pszWrite, pszRead, pszFill);
452#endif
453
454 LogFlow(("pdmR3DevHlp_MMIORegisterRC: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
455 return rc;
456}
457
458/** @interface_method_impl{PDMDEVHLPR3,pfnMMIORegisterR0} */
459static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTGCPHYS cbRange, RTR0PTR pvUser,
460 const char *pszWrite, const char *pszRead, const char *pszFill)
461{
462 PDMDEV_ASSERT_DEVINS(pDevIns);
463 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
464 Assert(pDevIns->pReg->pszR0Mod[0]);
465 Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0);
466 LogFlow(("pdmR3DevHlp_MMIORegisterHC: caller='%s'/%d: GCPhysStart=%RGp cbRange=%RGp pvUser=%p pszWrite=%p:{%s} pszRead=%p:{%s} pszFill=%p:{%s}\n",
467 pDevIns->pReg->szName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill));
468
469 /*
470 * Resolve the functions.
471 * Not all function have to present, leave it to IOM to enforce this.
472 */
473 int rc = VINF_SUCCESS;
474 if ( pDevIns->pReg->pszR0Mod[0]
475 && (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0))
476 {
477 R0PTRTYPE(PFNIOMMMIOWRITE) pfnR0PtrWrite = 0;
478 if (pszWrite)
479 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszWrite, &pfnR0PtrWrite);
480 R0PTRTYPE(PFNIOMMMIOREAD) pfnR0PtrRead = 0;
481 int rc2 = VINF_SUCCESS;
482 if (pszRead)
483 rc2 = pdmR3DevGetSymbolR0Lazy(pDevIns, pszRead, &pfnR0PtrRead);
484 R0PTRTYPE(PFNIOMMMIOFILL) pfnR0PtrFill = 0;
485 int rc3 = VINF_SUCCESS;
486 if (pszFill)
487 rc3 = pdmR3DevGetSymbolR0Lazy(pDevIns, pszFill, &pfnR0PtrFill);
488 if (RT_SUCCESS(rc) && RT_SUCCESS(rc2) && RT_SUCCESS(rc3))
489 rc = IOMR3MmioRegisterR0(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser,
490 pfnR0PtrWrite, pfnR0PtrRead, pfnR0PtrFill);
491 else
492 {
493 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszWrite)\n", pDevIns->pReg->pszR0Mod, pszWrite));
494 AssertMsgRC(rc2, ("Failed to resolve %s.%s (pszRead)\n", pDevIns->pReg->pszR0Mod, pszRead));
495 AssertMsgRC(rc3, ("Failed to resolve %s.%s (pszFill)\n", pDevIns->pReg->pszR0Mod, pszFill));
496 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
497 rc = rc2;
498 if (RT_FAILURE(rc3) && RT_SUCCESS(rc))
499 rc = rc3;
500 }
501 }
502 else
503 {
504 AssertMsgFailed(("No R0 module for this driver!\n"));
505 rc = VERR_INVALID_PARAMETER;
506 }
507
508 LogFlow(("pdmR3DevHlp_MMIORegisterR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
509 return rc;
510}
511
512
513/** @interface_method_impl{PDMDEVHLPR3,pfnMMIODeregister} */
514static DECLCALLBACK(int) pdmR3DevHlp_MMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTGCPHYS cbRange)
515{
516 PDMDEV_ASSERT_DEVINS(pDevIns);
517 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
518 LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: GCPhysStart=%RGp cbRange=%RGp\n",
519 pDevIns->pReg->szName, pDevIns->iInstance, GCPhysStart, cbRange));
520
521 int rc = IOMR3MmioDeregister(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange);
522
523 LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
524 return rc;
525}
526
527
528/**
529 * @copydoc PDMDEVHLPR3::pfnMMIO2Register
530 */
531static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Register(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS cb,
532 uint32_t fFlags, void **ppv, const char *pszDesc)
533{
534 PDMDEV_ASSERT_DEVINS(pDevIns);
535 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
536 LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: pPciDev=%p (%#x) iRegion=%#x cb=%#RGp fFlags=%RX32 ppv=%p pszDescp=%p:{%s}\n",
537 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion,
538 cb, fFlags, ppv, pszDesc, pszDesc));
539 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);
540
541/** @todo PGMR3PhysMMIO2Register mangles the description, move it here and
542 * use a real string cache. */
543 int rc = PGMR3PhysMMIO2Register(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion,
544 cb, fFlags, ppv, pszDesc);
545
546 LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
547 return rc;
548}
549
550
551/**
552 * @interface_method_impl{PDMDEVHLPR3,pfnMMIOExPreRegister}
553 */
554static DECLCALLBACK(int)
555pdmR3DevHlp_MMIOExPreRegister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS cbRegion, uint32_t fFlags,
556 const char *pszDesc,
557 RTHCPTR pvUser, PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
558 RTR0PTR pvUserR0, const char *pszWriteR0, const char *pszReadR0, const char *pszFillR0,
559 RTRCPTR pvUserRC, const char *pszWriteRC, const char *pszReadRC, const char *pszFillRC)
560{
561 PDMDEV_ASSERT_DEVINS(pDevIns);
562 PVM pVM = pDevIns->Internal.s.pVMR3;
563 VM_ASSERT_EMT(pVM);
564 LogFlow(("pdmR3DevHlp_MMIOExPreRegister: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x cbRegion=%#RGp fFlags=%RX32 pszDesc=%p:{%s}\n"
565 " pvUser=%p pfnWrite=%p pfnRead=%p pfnFill=%p\n"
566 " pvUserR0=%p pszWriteR0=%s pszReadR0=%s pszFillR0=%s\n"
567 " pvUserRC=%p pszWriteRC=%s pszReadRC=%s pszFillRC=%s\n",
568 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, cbRegion,
569 fFlags, pszDesc, pszDesc,
570 pvUser, pfnWrite, pfnRead, pfnFill,
571 pvUserR0, pszWriteR0, pszReadR0, pszFillR0,
572 pvUserRC, pszWriteRC, pszReadRC, pszFillRC));
573 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);
574
575 /*
576 * Resolve the functions.
577 */
578 AssertLogRelReturn( (!pszWriteR0 && !pszReadR0 && !pszFillR0)
579 || (pDevIns->pReg->pszR0Mod[0] && (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)),
580 VERR_INVALID_PARAMETER);
581 AssertLogRelReturn( (!pszWriteRC && !pszReadRC && !pszFillRC)
582 || (pDevIns->pReg->pszRCMod[0] && (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)),
583 VERR_INVALID_PARAMETER);
584
585 /* Ring-0 */
586 int rc;
587 R0PTRTYPE(PFNIOMMMIOWRITE) pfnWriteR0 = 0;
588 if (pszWriteR0)
589 {
590 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszWriteR0, &pfnWriteR0);
591 AssertLogRelMsgRCReturn(rc, ("pszWriteR0=%s rc=%Rrc\n", pszWriteR0, rc), rc);
592 }
593
594 R0PTRTYPE(PFNIOMMMIOREAD) pfnReadR0 = 0;
595 if (pszReadR0)
596 {
597 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszReadR0, &pfnReadR0);
598 AssertLogRelMsgRCReturn(rc, ("pszReadR0=%s rc=%Rrc\n", pszReadR0, rc), rc);
599 }
600 R0PTRTYPE(PFNIOMMMIOFILL) pfnFillR0 = 0;
601 if (pszFillR0)
602 {
603 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszFillR0, &pfnFillR0);
604 AssertLogRelMsgRCReturn(rc, ("pszFillR0=%s rc=%Rrc\n", pszFillR0, rc), rc);
605 }
606
607 /* Raw-mode */
608#if 0
609 RCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteRC = 0;
610 if (pszWriteRC)
611 {
612 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszWriteRC, &pfnWriteRC);
613 AssertLogRelMsgRCReturn(rc, ("pszWriteRC=%s rc=%Rrc\n", pszWriteRC, rc), rc);
614 }
615
616 RCPTRTYPE(PFNIOMMMIOREAD) pfnReadRC = 0;
617 if (pszReadRC)
618 {
619 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszReadRC, &pfnReadRC);
620 AssertLogRelMsgRCReturn(rc, ("pszReadRC=%s rc=%Rrc\n", pszReadRC, rc), rc);
621 }
622 RCPTRTYPE(PFNIOMMMIOFILL) pfnFillRC = 0;
623 if (pszFillRC)
624 {
625 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszFillRC, &pfnFillRC);
626 AssertLogRelMsgRCReturn(rc, ("pszFillRC=%s rc=%Rrc\n", pszFillRC, rc), rc);
627 }
628#else
629 RCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteRC = 0;
630 RCPTRTYPE(PFNIOMMMIOREAD) pfnReadRC = 0;
631 RCPTRTYPE(PFNIOMMMIOFILL) pfnFillRC = 0;
632 RT_NOREF(pszWriteRC, pszReadRC, pszFillRC);
633#endif
634
635
636 /*
637 * Call IOM to make the registration.
638 */
639 rc = IOMR3MmioExPreRegister(pVM, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion, cbRegion, fFlags, pszDesc,
640 pvUser, pfnWrite, pfnRead, pfnFill,
641 pvUserR0, pfnWriteR0, pfnReadR0, pfnFillR0,
642 pvUserRC, pfnWriteRC, pfnReadRC, pfnFillRC);
643
644 LogFlow(("pdmR3DevHlp_MMIOExPreRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
645 return rc;
646}
647
648
649/**
650 * @copydoc PDMDEVHLPR3::pfnMMIOExDeregister
651 */
652static DECLCALLBACK(int) pdmR3DevHlp_MMIOExDeregister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion)
653{
654 PDMDEV_ASSERT_DEVINS(pDevIns);
655 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
656 LogFlow(("pdmR3DevHlp_MMIOExDeregister: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x\n",
657 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion));
658
659 AssertReturn(iRegion <= UINT8_MAX || iRegion == UINT32_MAX, VERR_INVALID_PARAMETER);
660 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);
661
662 int rc = PGMR3PhysMMIOExDeregister(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion);
663
664 LogFlow(("pdmR3DevHlp_MMIOExDeregister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
665 return rc;
666}
667
668
669/**
670 * @copydoc PDMDEVHLPR3::pfnMMIOExMap
671 */
672static DECLCALLBACK(int) pdmR3DevHlp_MMIOExMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS GCPhys)
673{
674 PDMDEV_ASSERT_DEVINS(pDevIns);
675 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
676 LogFlow(("pdmR3DevHlp_MMIOExMap: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x GCPhys=%#RGp\n",
677 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, GCPhys));
678 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 != NULL, VERR_INVALID_PARAMETER);
679
680 int rc = PGMR3PhysMMIOExMap(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion, GCPhys);
681
682 LogFlow(("pdmR3DevHlp_MMIOExMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
683 return rc;
684}
685
686
687/**
688 * @copydoc PDMDEVHLPR3::pfnMMIOExUnmap
689 */
690static DECLCALLBACK(int) pdmR3DevHlp_MMIOExUnmap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS GCPhys)
691{
692 PDMDEV_ASSERT_DEVINS(pDevIns);
693 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
694 LogFlow(("pdmR3DevHlp_MMIOExUnmap: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x GCPhys=%#RGp\n",
695 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, GCPhys));
696 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 != NULL, VERR_INVALID_PARAMETER);
697
698 int rc = PGMR3PhysMMIOExUnmap(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion, GCPhys);
699
700 LogFlow(("pdmR3DevHlp_MMIOExUnmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
701 return rc;
702}
703
704
705/**
706 * @copydoc PDMDEVHLPR3::pfnMMIOExReduce
707 */
708static DECLCALLBACK(int) pdmR3DevHlp_MMIOExReduce(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS cbRegion)
709{
710 PDMDEV_ASSERT_DEVINS(pDevIns);
711 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
712 LogFlow(("pdmR3DevHlp_MMIOExReduce: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x cbRegion=%RGp\n",
713 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, cbRegion));
714 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 != NULL, VERR_INVALID_PARAMETER);
715
716 int rc = PGMR3PhysMMIOExReduce(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion, cbRegion);
717
718 LogFlow(("pdmR3DevHlp_MMIOExReduce: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
719 return rc;
720}
721
722
723/**
724 * @copydoc PDMDEVHLPR3::pfnMMHyperMapMMIO2
725 */
726static DECLCALLBACK(int) pdmR3DevHlp_MMHyperMapMMIO2(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS off,
727 RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr)
728{
729 PDMDEV_ASSERT_DEVINS(pDevIns);
730#ifndef PGM_WITHOUT_MAPPINGS
731 PVM pVM = pDevIns->Internal.s.pVMR3;
732 VM_ASSERT_EMT(pVM);
733 LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x off=%RGp cb=%RGp pszDesc=%p:{%s} pRCPtr=%p\n",
734 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, off, cb, pszDesc, pszDesc, pRCPtr));
735 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);
736
737 if (pDevIns->iInstance > 0)
738 {
739 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
740 if (pszDesc2)
741 pszDesc = pszDesc2;
742 }
743
744 int rc = MMR3HyperMapMMIO2(pVM, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion, off, cb, pszDesc, pRCPtr);
745
746#else
747 RT_NOREF(pDevIns, pPciDev, iRegion, off, cb, pszDesc, pRCPtr);
748 AssertFailed();
749 int rc = VERR_RAW_MODE_NOT_SUPPORTED;
750#endif
751 LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: returns %Rrc *pRCPtr=%RRv\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *pRCPtr));
752 return rc;
753}
754
755
756/**
757 * @copydoc PDMDEVHLPR3::pfnMMIO2MapKernel
758 */
759static DECLCALLBACK(int) pdmR3DevHlp_MMIO2MapKernel(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS off,
760 RTGCPHYS cb,const char *pszDesc, PRTR0PTR pR0Ptr)
761{
762 PDMDEV_ASSERT_DEVINS(pDevIns);
763 PVM pVM = pDevIns->Internal.s.pVMR3;
764 VM_ASSERT_EMT(pVM);
765 LogFlow(("pdmR3DevHlp_MMIO2MapKernel: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x off=%RGp cb=%RGp pszDesc=%p:{%s} pR0Ptr=%p\n",
766 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, off, cb, pszDesc, pszDesc, pR0Ptr));
767 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);
768
769 if (pDevIns->iInstance > 0)
770 {
771 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
772 if (pszDesc2)
773 pszDesc = pszDesc2;
774 }
775
776 int rc = PGMR3PhysMMIO2MapKernel(pVM, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion, off, cb, pszDesc, pR0Ptr);
777
778 LogFlow(("pdmR3DevHlp_MMIO2MapKernel: caller='%s'/%d: returns %Rrc *pR0Ptr=%RHv\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *pR0Ptr));
779 return rc;
780}
781
782
783/**
784 * @copydoc PDMDEVHLPR3::pfnMMIOExChangeRegionNo
785 */
786static DECLCALLBACK(int) pdmR3DevHlp_MMIOExChangeRegionNo(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
787 uint32_t iNewRegion)
788{
789 PDMDEV_ASSERT_DEVINS(pDevIns);
790 PVM pVM = pDevIns->Internal.s.pVMR3;
791 VM_ASSERT_EMT(pVM);
792 LogFlow(("pdmR3DevHlp_MMIOExChangeRegionNo: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x iNewRegion=%#x\n",
793 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, iNewRegion));
794 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);
795
796 int rc = PGMR3PhysMMIOExChangeRegionNo(pVM, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion, iNewRegion);
797
798 LogFlow(("pdmR3DevHlp_MMIOExChangeRegionNo: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
799 return rc;
800}
801
802
803/** @interface_method_impl{PDMDEVHLPR3,pfnROMRegister} */
804static DECLCALLBACK(int) pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange,
805 const void *pvBinary, uint32_t cbBinary, uint32_t fFlags, const char *pszDesc)
806{
807 PDMDEV_ASSERT_DEVINS(pDevIns);
808 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
809 LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: GCPhysStart=%RGp cbRange=%#x pvBinary=%p cbBinary=%#x fFlags=%#RX32 pszDesc=%p:{%s}\n",
810 pDevIns->pReg->szName, pDevIns->iInstance, GCPhysStart, cbRange, pvBinary, cbBinary, fFlags, pszDesc, pszDesc));
811
812/** @todo can we mangle pszDesc? */
813 int rc = PGMR3PhysRomRegister(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvBinary, cbBinary, fFlags, pszDesc);
814
815 LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
816 return rc;
817}
818
819
820/** @interface_method_impl{PDMDEVHLPR3,pfnROMProtectShadow} */
821static DECLCALLBACK(int) pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, PGMROMPROT enmProt)
822{
823 PDMDEV_ASSERT_DEVINS(pDevIns);
824 LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: GCPhysStart=%RGp cbRange=%#x enmProt=%d\n",
825 pDevIns->pReg->szName, pDevIns->iInstance, GCPhysStart, cbRange, enmProt));
826
827 int rc = PGMR3PhysRomProtect(pDevIns->Internal.s.pVMR3, GCPhysStart, cbRange, enmProt);
828
829 LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
830 return rc;
831}
832
833
834/** @interface_method_impl{PDMDEVHLPR3,pfnSSMRegister} */
835static DECLCALLBACK(int) pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, uint32_t uVersion, size_t cbGuess, const char *pszBefore,
836 PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote,
837 PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
838 PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
839{
840 PDMDEV_ASSERT_DEVINS(pDevIns);
841 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
842 LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: uVersion=%#x cbGuess=%#x pszBefore=%p:{%s}\n"
843 " pfnLivePrep=%p pfnLiveExec=%p pfnLiveVote=%p pfnSavePrep=%p pfnSaveExec=%p pfnSaveDone=%p pszLoadPrep=%p pfnLoadExec=%p pfnLoadDone=%p\n",
844 pDevIns->pReg->szName, pDevIns->iInstance, uVersion, cbGuess, pszBefore, pszBefore,
845 pfnLivePrep, pfnLiveExec, pfnLiveVote,
846 pfnSavePrep, pfnSaveExec, pfnSaveDone,
847 pfnLoadPrep, pfnLoadExec, pfnLoadDone));
848
849 int rc = SSMR3RegisterDevice(pDevIns->Internal.s.pVMR3, pDevIns, pDevIns->pReg->szName, pDevIns->iInstance,
850 uVersion, cbGuess, pszBefore,
851 pfnLivePrep, pfnLiveExec, pfnLiveVote,
852 pfnSavePrep, pfnSaveExec, pfnSaveDone,
853 pfnLoadPrep, pfnLoadExec, pfnLoadDone);
854
855 LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
856 return rc;
857}
858
859
860/** @interface_method_impl{PDMDEVHLPR3,pfnTMTimerCreate} */
861static DECLCALLBACK(int) pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer)
862{
863 PDMDEV_ASSERT_DEVINS(pDevIns);
864 PVM pVM = pDevIns->Internal.s.pVMR3;
865 VM_ASSERT_EMT(pVM);
866 LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pvUser=%p fFlags=%#x pszDesc=%p:{%s} ppTimer=%p\n",
867 pDevIns->pReg->szName, pDevIns->iInstance, enmClock, pfnCallback, pvUser, fFlags, pszDesc, pszDesc, ppTimer));
868
869 if (pDevIns->iInstance > 0) /** @todo use a string cache here later. */
870 {
871 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
872 if (pszDesc2)
873 pszDesc = pszDesc2;
874 }
875
876 int rc = TMR3TimerCreateDevice(pVM, pDevIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, ppTimer);
877
878 LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
879 return rc;
880}
881
882
883
884/** @interface_method_impl{PDMDEVHLPR3,pfnTimerCreate} */
885static DECLCALLBACK(int) pdmR3DevHlp_TimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback,
886 void *pvUser, uint32_t fFlags, const char *pszDesc, PTMTIMERHANDLE phTimer)
887{
888 PDMDEV_ASSERT_DEVINS(pDevIns);
889 PVM pVM = pDevIns->Internal.s.pVMR3;
890 VM_ASSERT_EMT(pVM);
891 LogFlow(("pdmR3DevHlp_TimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pvUser=%p fFlags=%#x pszDesc=%p:{%s} phTimer=%p\n",
892 pDevIns->pReg->szName, pDevIns->iInstance, enmClock, pfnCallback, pvUser, fFlags, pszDesc, pszDesc, phTimer));
893
894 if (pDevIns->iInstance > 0) /** @todo use a string cache here later. */
895 {
896 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
897 if (pszDesc2)
898 pszDesc = pszDesc2;
899 }
900
901 PTMTIMER pTimer = NULL;
902 int rc = TMR3TimerCreateDevice(pVM, pDevIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, &pTimer);
903 *phTimer = (uintptr_t)pTimer;
904
905 LogFlow(("pdmR3DevHlp_TimerCreate: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
906 return rc;
907}
908
909
910/** @interface_method_impl{PDMDEVHLPR3,pfnTimerToPtr} */
911static DECLCALLBACK(PTMTIMERR3) pdmR3DevHlp_TimerToPtr(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
912{
913 PDMDEV_ASSERT_DEVINS(pDevIns);
914 RT_NOREF(pDevIns);
915 return (PTMTIMERR3)hTimer;
916}
917
918
919/** @interface_method_impl{PDMDEVHLPR3,pfnTimerFromMicro} */
920static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerFromMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicroSecs)
921{
922 return TMTimerFromMicro(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer), cMicroSecs);
923}
924
925
926/** @interface_method_impl{PDMDEVHLPR3,pfnTimerFromMilli} */
927static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerFromMilli(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliSecs)
928{
929 return TMTimerFromMilli(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer), cMilliSecs);
930}
931
932
933/** @interface_method_impl{PDMDEVHLPR3,pfnTimerFromNano} */
934static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerFromNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanoSecs)
935{
936 return TMTimerFromNano(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer), cNanoSecs);
937}
938
939/** @interface_method_impl{PDMDEVHLPR3,pfnTimerGet} */
940static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerGet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
941{
942 return TMTimerGet(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer));
943}
944
945
946/** @interface_method_impl{PDMDEVHLPR3,pfnTimerGetFreq} */
947static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerGetFreq(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
948{
949 return TMTimerGetFreq(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer));
950}
951
952
953/** @interface_method_impl{PDMDEVHLPR3,pfnTimerGetNano} */
954static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerGetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
955{
956 return TMTimerGetNano(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer));
957}
958
959
960/** @interface_method_impl{PDMDEVHLPR3,pfnTimerIsActive} */
961static DECLCALLBACK(bool) pdmR3DevHlp_TimerIsActive(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
962{
963 return TMTimerIsActive(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer));
964}
965
966
967/** @interface_method_impl{PDMDEVHLPR3,pfnTimerIsLockOwner} */
968static DECLCALLBACK(bool) pdmR3DevHlp_TimerIsLockOwner(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
969{
970 return TMTimerIsLockOwner(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer));
971}
972
973
974/** @interface_method_impl{PDMDEVHLPR3,pfnTimerLock} */
975static DECLCALLBACK(int) pdmR3DevHlp_TimerLock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, int rcBusy)
976{
977 return TMTimerLock(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer), rcBusy);
978}
979
980
981/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSet} */
982static DECLCALLBACK(int) pdmR3DevHlp_TimerSet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t uExpire)
983{
984 return TMTimerSet(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer), uExpire);
985}
986
987
988/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetFrequencyHint} */
989static DECLCALLBACK(int) pdmR3DevHlp_TimerSetFrequencyHint(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint32_t uHz)
990{
991 return TMTimerSetFrequencyHint(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer), uHz);
992}
993
994
995/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetMicro} */
996static DECLCALLBACK(int) pdmR3DevHlp_TimerSetMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext)
997{
998 return TMTimerSetMicro(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer), cMicrosToNext);
999}
1000
1001
1002/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetMillies} */
1003static DECLCALLBACK(int) pdmR3DevHlp_TimerSetMillies(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext)
1004{
1005 return TMTimerSetMillies(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer), cMilliesToNext);
1006}
1007
1008
1009/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetNano} */
1010static DECLCALLBACK(int) pdmR3DevHlp_TimerSetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanosToNext)
1011{
1012 return TMTimerSetNano(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer), cNanosToNext);
1013}
1014
1015
1016/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetRelative} */
1017static DECLCALLBACK(int) pdmR3DevHlp_TimerSetRelative(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now)
1018{
1019 return TMTimerSetRelative(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer), cTicksToNext, pu64Now);
1020}
1021
1022
1023/** @interface_method_impl{PDMDEVHLPR3,pfnTimerStop} */
1024static DECLCALLBACK(int) pdmR3DevHlp_TimerStop(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
1025{
1026 return TMTimerStop(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer));
1027}
1028
1029
1030/** @interface_method_impl{PDMDEVHLPR3,pfnTimerUnlock} */
1031static DECLCALLBACK(void) pdmR3DevHlp_TimerUnlock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
1032{
1033 TMTimerUnlock(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer));
1034}
1035
1036
1037/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSave} */
1038static DECLCALLBACK(int) pdmR3DevHlp_TimerSave(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM)
1039{
1040 return TMR3TimerSave(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer), pSSM);
1041}
1042
1043
1044/** @interface_method_impl{PDMDEVHLPR3,pfnTimerLoad} */
1045static DECLCALLBACK(int) pdmR3DevHlp_TimerLoad(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM)
1046{
1047 return TMR3TimerLoad(pdmR3DevHlp_TimerToPtr(pDevIns, hTimer), pSSM);
1048}
1049
1050
1051/** @interface_method_impl{PDMDEVHLPR3,pfnTMUtcNow} */
1052static DECLCALLBACK(PRTTIMESPEC) pdmR3DevHlp_TMUtcNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime)
1053{
1054 PDMDEV_ASSERT_DEVINS(pDevIns);
1055 LogFlow(("pdmR3DevHlp_TMUtcNow: caller='%s'/%d: pTime=%p\n",
1056 pDevIns->pReg->szName, pDevIns->iInstance, pTime));
1057
1058 pTime = TMR3UtcNow(pDevIns->Internal.s.pVMR3, pTime);
1059
1060 LogFlow(("pdmR3DevHlp_TMUtcNow: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, RTTimeSpecGetNano(pTime)));
1061 return pTime;
1062}
1063
1064
1065/** @interface_method_impl{PDMDEVHLPR3,pfnTMTimeVirtGet} */
1066static DECLCALLBACK(uint64_t) pdmR3DevHlp_TMTimeVirtGet(PPDMDEVINS pDevIns)
1067{
1068 PDMDEV_ASSERT_DEVINS(pDevIns);
1069 LogFlow(("pdmR3DevHlp_TMTimeVirtGet: caller='%s'/%d\n",
1070 pDevIns->pReg->szName, pDevIns->iInstance));
1071
1072 uint64_t u64Time = TMVirtualSyncGet(pDevIns->Internal.s.pVMR3);
1073
1074 LogFlow(("pdmR3DevHlp_TMTimeVirtGet: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, u64Time));
1075 return u64Time;
1076}
1077
1078
1079/** @interface_method_impl{PDMDEVHLPR3,pfnTMTimeVirtGetFreq} */
1080static DECLCALLBACK(uint64_t) pdmR3DevHlp_TMTimeVirtGetFreq(PPDMDEVINS pDevIns)
1081{
1082 PDMDEV_ASSERT_DEVINS(pDevIns);
1083 LogFlow(("pdmR3DevHlp_TMTimeVirtGetFreq: caller='%s'/%d\n",
1084 pDevIns->pReg->szName, pDevIns->iInstance));
1085
1086 uint64_t u64Freq = TMVirtualGetFreq(pDevIns->Internal.s.pVMR3);
1087
1088 LogFlow(("pdmR3DevHlp_TMTimeVirtGetFreq: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, u64Freq));
1089 return u64Freq;
1090}
1091
1092
1093/** @interface_method_impl{PDMDEVHLPR3,pfnTMTimeVirtGetNano} */
1094static DECLCALLBACK(uint64_t) pdmR3DevHlp_TMTimeVirtGetNano(PPDMDEVINS pDevIns)
1095{
1096 PDMDEV_ASSERT_DEVINS(pDevIns);
1097 LogFlow(("pdmR3DevHlp_TMTimeVirtGetNano: caller='%s'/%d\n",
1098 pDevIns->pReg->szName, pDevIns->iInstance));
1099
1100 uint64_t u64Time = TMVirtualGet(pDevIns->Internal.s.pVMR3);
1101 uint64_t u64Nano = TMVirtualToNano(pDevIns->Internal.s.pVMR3, u64Time);
1102
1103 LogFlow(("pdmR3DevHlp_TMTimeVirtGetNano: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, u64Nano));
1104 return u64Nano;
1105}
1106
1107
1108/** @interface_method_impl{PDMDEVHLPR3,pfnGetSupDrvSession} */
1109static DECLCALLBACK(PSUPDRVSESSION) pdmR3DevHlp_GetSupDrvSession(PPDMDEVINS pDevIns)
1110{
1111 PDMDEV_ASSERT_DEVINS(pDevIns);
1112 LogFlow(("pdmR3DevHlp_GetSupDrvSession: caller='%s'/%d\n",
1113 pDevIns->pReg->szName, pDevIns->iInstance));
1114
1115 PSUPDRVSESSION pSession = pDevIns->Internal.s.pVMR3->pSession;
1116
1117 LogFlow(("pdmR3DevHlp_GetSupDrvSession: caller='%s'/%d: returns %#p\n", pDevIns->pReg->szName, pDevIns->iInstance, pSession));
1118 return pSession;
1119}
1120
1121
1122/** @interface_method_impl{PDMDEVHLPR3,pfnQueryGenericUserObject} */
1123static DECLCALLBACK(void *) pdmR3DevHlp_QueryGenericUserObject(PPDMDEVINS pDevIns, PCRTUUID pUuid)
1124{
1125 PDMDEV_ASSERT_DEVINS(pDevIns);
1126 LogFlow(("pdmR3DevHlp_QueryGenericUserObject: caller='%s'/%d: pUuid=%p:%RTuuid\n",
1127 pDevIns->pReg->szName, pDevIns->iInstance, pUuid, pUuid));
1128
1129#if defined(DEBUG_bird) || defined(DEBUG_ramshankar) || defined(DEBUG_sunlover) || defined(DEBUG_michael) || defined(DEBUG_andy)
1130 AssertMsgFailed(("'%s' wants %RTuuid - external only interface!\n", pDevIns->pReg->szName, pUuid));
1131#endif
1132
1133 void *pvRet;
1134 PUVM pUVM = pDevIns->Internal.s.pVMR3->pUVM;
1135 if (pUVM->pVmm2UserMethods->pfnQueryGenericObject)
1136 pvRet = pUVM->pVmm2UserMethods->pfnQueryGenericObject(pUVM->pVmm2UserMethods, pUVM, pUuid);
1137 else
1138 pvRet = NULL;
1139
1140 LogRel(("pdmR3DevHlp_QueryGenericUserObject: caller='%s'/%d: returns %#p for %RTuuid\n",
1141 pDevIns->pReg->szName, pDevIns->iInstance, pvRet, pUuid));
1142 return pvRet;
1143}
1144
1145
1146/** @interface_method_impl{PDMDEVHLPR3,pfnPhysRead} */
1147static DECLCALLBACK(int) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
1148{
1149 PDMDEV_ASSERT_DEVINS(pDevIns);
1150 PVM pVM = pDevIns->Internal.s.pVMR3;
1151 LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
1152 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
1153
1154#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
1155 if (!VM_IS_EMT(pVM))
1156 {
1157 char szNames[128];
1158 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
1159 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
1160 }
1161#endif
1162
1163 VBOXSTRICTRC rcStrict;
1164 if (VM_IS_EMT(pVM))
1165 rcStrict = PGMPhysRead(pVM, GCPhys, pvBuf, cbRead, PGMACCESSORIGIN_DEVICE);
1166 else
1167 rcStrict = PGMR3PhysReadExternal(pVM, GCPhys, pvBuf, cbRead, PGMACCESSORIGIN_DEVICE);
1168 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
1169
1170 Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
1171 return VBOXSTRICTRC_VAL(rcStrict);
1172}
1173
1174
1175/** @interface_method_impl{PDMDEVHLPR3,pfnPhysWrite} */
1176static DECLCALLBACK(int) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
1177{
1178 PDMDEV_ASSERT_DEVINS(pDevIns);
1179 PVM pVM = pDevIns->Internal.s.pVMR3;
1180 LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
1181 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
1182
1183#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
1184 if (!VM_IS_EMT(pVM))
1185 {
1186 char szNames[128];
1187 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
1188 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
1189 }
1190#endif
1191
1192 VBOXSTRICTRC rcStrict;
1193 if (VM_IS_EMT(pVM))
1194 rcStrict = PGMPhysWrite(pVM, GCPhys, pvBuf, cbWrite, PGMACCESSORIGIN_DEVICE);
1195 else
1196 rcStrict = PGMR3PhysWriteExternal(pVM, GCPhys, pvBuf, cbWrite, PGMACCESSORIGIN_DEVICE);
1197 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
1198
1199 Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
1200 return VBOXSTRICTRC_VAL(rcStrict);
1201}
1202
1203
1204/** @interface_method_impl{PDMDEVHLPR3,pfnPhysGCPhys2CCPtr} */
1205static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPhys2CCPtr(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, void **ppv, PPGMPAGEMAPLOCK pLock)
1206{
1207 PDMDEV_ASSERT_DEVINS(pDevIns);
1208 PVM pVM = pDevIns->Internal.s.pVMR3;
1209 LogFlow(("pdmR3DevHlp_PhysGCPhys2CCPtr: caller='%s'/%d: GCPhys=%RGp fFlags=%#x ppv=%p pLock=%p\n",
1210 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, fFlags, ppv, pLock));
1211 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
1212
1213#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
1214 if (!VM_IS_EMT(pVM))
1215 {
1216 char szNames[128];
1217 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
1218 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
1219 }
1220#endif
1221
1222 int rc = PGMR3PhysGCPhys2CCPtrExternal(pVM, GCPhys, ppv, pLock);
1223
1224 Log(("pdmR3DevHlp_PhysGCPhys2CCPtr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1225 return rc;
1226}
1227
1228
1229/** @interface_method_impl{PDMDEVHLPR3,pfnPhysGCPhys2CCPtrReadOnly} */
1230static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, const void **ppv, PPGMPAGEMAPLOCK pLock)
1231{
1232 PDMDEV_ASSERT_DEVINS(pDevIns);
1233 PVM pVM = pDevIns->Internal.s.pVMR3;
1234 LogFlow(("pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly: caller='%s'/%d: GCPhys=%RGp fFlags=%#x ppv=%p pLock=%p\n",
1235 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, fFlags, ppv, pLock));
1236 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
1237
1238#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
1239 if (!VM_IS_EMT(pVM))
1240 {
1241 char szNames[128];
1242 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
1243 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
1244 }
1245#endif
1246
1247 int rc = PGMR3PhysGCPhys2CCPtrReadOnlyExternal(pVM, GCPhys, ppv, pLock);
1248
1249 Log(("pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1250 return rc;
1251}
1252
1253
1254/** @interface_method_impl{PDMDEVHLPR3,pfnPhysReleasePageMappingLock} */
1255static DECLCALLBACK(void) pdmR3DevHlp_PhysReleasePageMappingLock(PPDMDEVINS pDevIns, PPGMPAGEMAPLOCK pLock)
1256{
1257 PDMDEV_ASSERT_DEVINS(pDevIns);
1258 PVM pVM = pDevIns->Internal.s.pVMR3;
1259 LogFlow(("pdmR3DevHlp_PhysReleasePageMappingLock: caller='%s'/%d: pLock=%p\n",
1260 pDevIns->pReg->szName, pDevIns->iInstance, pLock));
1261
1262 PGMPhysReleasePageMappingLock(pVM, pLock);
1263
1264 Log(("pdmR3DevHlp_PhysReleasePageMappingLock: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1265}
1266
1267
1268/** @interface_method_impl{PDMDEVHLPR3,pfnPhysBulkGCPhys2CCPtr} */
1269static DECLCALLBACK(int) pdmR3DevHlp_PhysBulkGCPhys2CCPtr(PPDMDEVINS pDevIns, uint32_t cPages, PCRTGCPHYS paGCPhysPages,
1270 uint32_t fFlags, void **papvPages, PPGMPAGEMAPLOCK paLocks)
1271{
1272 PDMDEV_ASSERT_DEVINS(pDevIns);
1273 PVM pVM = pDevIns->Internal.s.pVMR3;
1274 LogFlow(("pdmR3DevHlp_PhysBulkGCPhys2CCPtr: caller='%s'/%d: cPages=%#x paGCPhysPages=%p (%RGp,..) fFlags=%#x papvPages=%p paLocks=%p\n",
1275 pDevIns->pReg->szName, pDevIns->iInstance, cPages, paGCPhysPages, paGCPhysPages[0], fFlags, papvPages, paLocks));
1276 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
1277 AssertReturn(cPages > 0, VERR_INVALID_PARAMETER);
1278
1279#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
1280 if (!VM_IS_EMT(pVM))
1281 {
1282 char szNames[128];
1283 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
1284 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
1285 }
1286#endif
1287
1288 int rc = PGMR3PhysBulkGCPhys2CCPtrExternal(pVM, cPages, paGCPhysPages, papvPages, paLocks);
1289
1290 Log(("pdmR3DevHlp_PhysBulkGCPhys2CCPtr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1291 return rc;
1292}
1293
1294
1295/** @interface_method_impl{PDMDEVHLPR3,pfnPhysBulkGCPhys2CCPtrReadOnly} */
1296static DECLCALLBACK(int) pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, uint32_t cPages, PCRTGCPHYS paGCPhysPages,
1297 uint32_t fFlags, const void **papvPages, PPGMPAGEMAPLOCK paLocks)
1298{
1299 PDMDEV_ASSERT_DEVINS(pDevIns);
1300 PVM pVM = pDevIns->Internal.s.pVMR3;
1301 LogFlow(("pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly: caller='%s'/%d: cPages=%#x paGCPhysPages=%p (%RGp,...) fFlags=%#x papvPages=%p paLocks=%p\n",
1302 pDevIns->pReg->szName, pDevIns->iInstance, cPages, paGCPhysPages, paGCPhysPages[0], fFlags, papvPages, paLocks));
1303 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
1304 AssertReturn(cPages > 0, VERR_INVALID_PARAMETER);
1305
1306#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
1307 if (!VM_IS_EMT(pVM))
1308 {
1309 char szNames[128];
1310 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
1311 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
1312 }
1313#endif
1314
1315 int rc = PGMR3PhysBulkGCPhys2CCPtrReadOnlyExternal(pVM, cPages, paGCPhysPages, papvPages, paLocks);
1316
1317 Log(("pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1318 return rc;
1319}
1320
1321
1322/** @interface_method_impl{PDMDEVHLPR3,pfnPhysBulkReleasePageMappingLocks} */
1323static DECLCALLBACK(void) pdmR3DevHlp_PhysBulkReleasePageMappingLocks(PPDMDEVINS pDevIns, uint32_t cPages, PPGMPAGEMAPLOCK paLocks)
1324{
1325 PDMDEV_ASSERT_DEVINS(pDevIns);
1326 PVM pVM = pDevIns->Internal.s.pVMR3;
1327 LogFlow(("pdmR3DevHlp_PhysBulkReleasePageMappingLocks: caller='%s'/%d: cPages=%#x paLocks=%p\n",
1328 pDevIns->pReg->szName, pDevIns->iInstance, cPages, paLocks));
1329 Assert(cPages > 0);
1330
1331 PGMPhysBulkReleasePageMappingLocks(pVM, cPages, paLocks);
1332
1333 Log(("pdmR3DevHlp_PhysBulkReleasePageMappingLocks: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1334}
1335
1336
1337/** @interface_method_impl{PDMDEVHLPR3,pfnPhysReadGCVirt} */
1338static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
1339{
1340 PDMDEV_ASSERT_DEVINS(pDevIns);
1341 PVM pVM = pDevIns->Internal.s.pVMR3;
1342 VM_ASSERT_EMT(pVM);
1343 LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: pvDst=%p GCVirt=%RGv cb=%#x\n",
1344 pDevIns->pReg->szName, pDevIns->iInstance, pvDst, GCVirtSrc, cb));
1345
1346 PVMCPU pVCpu = VMMGetCpu(pVM);
1347 if (!pVCpu)
1348 return VERR_ACCESS_DENIED;
1349#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
1350 /** @todo SMP. */
1351#endif
1352
1353 int rc = PGMPhysSimpleReadGCPtr(pVCpu, pvDst, GCVirtSrc, cb);
1354
1355 LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1356
1357 return rc;
1358}
1359
1360
1361/** @interface_method_impl{PDMDEVHLPR3,pfnPhysWriteGCVirt} */
1362static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
1363{
1364 PDMDEV_ASSERT_DEVINS(pDevIns);
1365 PVM pVM = pDevIns->Internal.s.pVMR3;
1366 VM_ASSERT_EMT(pVM);
1367 LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: GCVirtDst=%RGv pvSrc=%p cb=%#x\n",
1368 pDevIns->pReg->szName, pDevIns->iInstance, GCVirtDst, pvSrc, cb));
1369
1370 PVMCPU pVCpu = VMMGetCpu(pVM);
1371 if (!pVCpu)
1372 return VERR_ACCESS_DENIED;
1373#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
1374 /** @todo SMP. */
1375#endif
1376
1377 int rc = PGMPhysSimpleWriteGCPtr(pVCpu, GCVirtDst, pvSrc, cb);
1378
1379 LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1380
1381 return rc;
1382}
1383
1384
1385/** @interface_method_impl{PDMDEVHLPR3,pfnPhysGCPtr2GCPhys} */
1386static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys)
1387{
1388 PDMDEV_ASSERT_DEVINS(pDevIns);
1389 PVM pVM = pDevIns->Internal.s.pVMR3;
1390 VM_ASSERT_EMT(pVM);
1391 LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: GCPtr=%RGv pGCPhys=%p\n",
1392 pDevIns->pReg->szName, pDevIns->iInstance, GCPtr, pGCPhys));
1393
1394 PVMCPU pVCpu = VMMGetCpu(pVM);
1395 if (!pVCpu)
1396 return VERR_ACCESS_DENIED;
1397#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
1398 /** @todo SMP. */
1399#endif
1400
1401 int rc = PGMPhysGCPtr2GCPhys(pVCpu, GCPtr, pGCPhys);
1402
1403 LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: returns %Rrc *pGCPhys=%RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *pGCPhys));
1404
1405 return rc;
1406}
1407
1408
1409/** @interface_method_impl{PDMDEVHLPR3,pfnMMHeapAlloc} */
1410static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb)
1411{
1412 PDMDEV_ASSERT_DEVINS(pDevIns);
1413 LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: cb=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cb));
1414
1415 void *pv = MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE_USER, cb);
1416
1417 LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pv));
1418 return pv;
1419}
1420
1421
1422/** @interface_method_impl{PDMDEVHLPR3,pfnMMHeapAllocZ} */
1423static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb)
1424{
1425 PDMDEV_ASSERT_DEVINS(pDevIns);
1426 LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: cb=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cb));
1427
1428 void *pv = MMR3HeapAllocZ(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE_USER, cb);
1429
1430 LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pv));
1431 return pv;
1432}
1433
1434
1435/** @interface_method_impl{PDMDEVHLPR3,pfnMMHeapFree} */
1436static DECLCALLBACK(void) pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv)
1437{
1438 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
1439 LogFlow(("pdmR3DevHlp_MMHeapFree: caller='%s'/%d: pv=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pv));
1440
1441 MMR3HeapFree(pv);
1442
1443 LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1444}
1445
1446
1447/** @interface_method_impl{PDMDEVHLPR3,pfnVMState} */
1448static DECLCALLBACK(VMSTATE) pdmR3DevHlp_VMState(PPDMDEVINS pDevIns)
1449{
1450 PDMDEV_ASSERT_DEVINS(pDevIns);
1451
1452 VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
1453
1454 LogFlow(("pdmR3DevHlp_VMState: caller='%s'/%d: returns %d (%s)\n", pDevIns->pReg->szName, pDevIns->iInstance,
1455 enmVMState, VMR3GetStateName(enmVMState)));
1456 return enmVMState;
1457}
1458
1459
1460/** @interface_method_impl{PDMDEVHLPR3,pfnVMTeleportedAndNotFullyResumedYet} */
1461static DECLCALLBACK(bool) pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet(PPDMDEVINS pDevIns)
1462{
1463 PDMDEV_ASSERT_DEVINS(pDevIns);
1464
1465 bool fRc = VMR3TeleportedAndNotFullyResumedYet(pDevIns->Internal.s.pVMR3);
1466
1467 LogFlow(("pdmR3DevHlp_VMState: caller='%s'/%d: returns %RTbool\n", pDevIns->pReg->szName, pDevIns->iInstance,
1468 fRc));
1469 return fRc;
1470}
1471
1472
1473/** @interface_method_impl{PDMDEVHLPR3,pfnVMSetError} */
1474static DECLCALLBACK(int) pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
1475{
1476 PDMDEV_ASSERT_DEVINS(pDevIns);
1477 va_list args;
1478 va_start(args, pszFormat);
1479 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR3, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
1480 va_end(args);
1481 return rc;
1482}
1483
1484
1485/** @interface_method_impl{PDMDEVHLPR3,pfnVMSetErrorV} */
1486static DECLCALLBACK(int) pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
1487{
1488 PDMDEV_ASSERT_DEVINS(pDevIns);
1489 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR3, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
1490 return rc;
1491}
1492
1493
1494/** @interface_method_impl{PDMDEVHLPR3,pfnVMSetRuntimeError} */
1495static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
1496{
1497 PDMDEV_ASSERT_DEVINS(pDevIns);
1498 va_list args;
1499 va_start(args, pszFormat);
1500 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR3, fFlags, pszErrorId, pszFormat, args);
1501 va_end(args);
1502 return rc;
1503}
1504
1505
1506/** @interface_method_impl{PDMDEVHLPR3,pfnVMSetRuntimeErrorV} */
1507static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
1508{
1509 PDMDEV_ASSERT_DEVINS(pDevIns);
1510 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR3, fFlags, pszErrorId, pszFormat, va);
1511 return rc;
1512}
1513
1514
1515/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFStopV} */
1516static DECLCALLBACK(int) pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args)
1517{
1518 PDMDEV_ASSERT_DEVINS(pDevIns);
1519#ifdef LOG_ENABLED
1520 va_list va2;
1521 va_copy(va2, args);
1522 LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: pszFile=%p:{%s} iLine=%d pszFunction=%p:{%s} pszFormat=%p:{%s} (%N)\n",
1523 pDevIns->pReg->szName, pDevIns->iInstance, pszFile, pszFile, iLine, pszFunction, pszFunction, pszFormat, pszFormat, pszFormat, &va2));
1524 va_end(va2);
1525#endif
1526
1527 PVM pVM = pDevIns->Internal.s.pVMR3;
1528 VM_ASSERT_EMT(pVM);
1529 int rc = DBGFR3EventSrcV(pVM, DBGFEVENT_DEV_STOP, pszFile, iLine, pszFunction, pszFormat, args);
1530 if (rc == VERR_DBGF_NOT_ATTACHED)
1531 rc = VINF_SUCCESS;
1532
1533 LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1534 return rc;
1535}
1536
1537
1538/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFInfoRegister} */
1539static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)
1540{
1541 PDMDEV_ASSERT_DEVINS(pDevIns);
1542 LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
1543 pDevIns->pReg->szName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
1544
1545 PVM pVM = pDevIns->Internal.s.pVMR3;
1546 VM_ASSERT_EMT(pVM);
1547 int rc = DBGFR3InfoRegisterDevice(pVM, pszName, pszDesc, pfnHandler, pDevIns);
1548
1549 LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1550 return rc;
1551}
1552
1553
1554/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFInfoRegisterArgv} */
1555static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegisterArgv(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVDEV pfnHandler)
1556{
1557 PDMDEV_ASSERT_DEVINS(pDevIns);
1558 LogFlow(("pdmR3DevHlp_DBGFInfoRegisterArgv: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
1559 pDevIns->pReg->szName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
1560
1561 PVM pVM = pDevIns->Internal.s.pVMR3;
1562 VM_ASSERT_EMT(pVM);
1563 int rc = DBGFR3InfoRegisterDeviceArgv(pVM, pszName, pszDesc, pfnHandler, pDevIns);
1564
1565 LogFlow(("pdmR3DevHlp_DBGFInfoRegisterArgv: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1566 return rc;
1567}
1568
1569
1570/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFRegRegister} */
1571static DECLCALLBACK(int) pdmR3DevHlp_DBGFRegRegister(PPDMDEVINS pDevIns, PCDBGFREGDESC paRegisters)
1572{
1573 PDMDEV_ASSERT_DEVINS(pDevIns);
1574 LogFlow(("pdmR3DevHlp_DBGFRegRegister: caller='%s'/%d: paRegisters=%p\n",
1575 pDevIns->pReg->szName, pDevIns->iInstance, paRegisters));
1576
1577 PVM pVM = pDevIns->Internal.s.pVMR3;
1578 VM_ASSERT_EMT(pVM);
1579 int rc = DBGFR3RegRegisterDevice(pVM, paRegisters, pDevIns, pDevIns->pReg->szName, pDevIns->iInstance);
1580
1581 LogFlow(("pdmR3DevHlp_DBGFRegRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1582 return rc;
1583}
1584
1585
1586/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFTraceBuf} */
1587static DECLCALLBACK(RTTRACEBUF) pdmR3DevHlp_DBGFTraceBuf(PPDMDEVINS pDevIns)
1588{
1589 PDMDEV_ASSERT_DEVINS(pDevIns);
1590 RTTRACEBUF hTraceBuf = pDevIns->Internal.s.pVMR3->hTraceBufR3;
1591 LogFlow(("pdmR3DevHlp_DBGFTraceBuf: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, hTraceBuf));
1592 return hTraceBuf;
1593}
1594
1595
1596/** @interface_method_impl{PDMDEVHLPR3,pfnSTAMRegister} */
1597static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName,
1598 STAMUNIT enmUnit, const char *pszDesc)
1599{
1600 PDMDEV_ASSERT_DEVINS(pDevIns);
1601 PVM pVM = pDevIns->Internal.s.pVMR3;
1602 VM_ASSERT_EMT(pVM);
1603
1604 STAM_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc);
1605 RT_NOREF_PV(pVM); RT_NOREF6(pDevIns, pvSample, enmType, pszName, enmUnit, pszDesc);
1606}
1607
1608
1609
1610/** @interface_method_impl{PDMDEVHLPR3,pfnSTAMRegisterF} */
1611static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
1612 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...)
1613{
1614 PDMDEV_ASSERT_DEVINS(pDevIns);
1615 PVM pVM = pDevIns->Internal.s.pVMR3;
1616 VM_ASSERT_EMT(pVM);
1617
1618 va_list args;
1619 va_start(args, pszName);
1620 int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
1621 va_end(args);
1622 AssertRC(rc);
1623
1624 NOREF(pVM);
1625}
1626
1627
1628/** @interface_method_impl{PDMDEVHLPR3,pfnSTAMRegisterV} */
1629static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
1630 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)
1631{
1632 PDMDEV_ASSERT_DEVINS(pDevIns);
1633 PVM pVM = pDevIns->Internal.s.pVMR3;
1634 VM_ASSERT_EMT(pVM);
1635
1636 int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
1637 AssertRC(rc);
1638
1639 NOREF(pVM);
1640}
1641
1642
1643/**
1644 * @interface_method_impl{PDMDEVHLPR3,pfnPCIRegister}
1645 */
1646static DECLCALLBACK(int) pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t fFlags,
1647 uint8_t uPciDevNo, uint8_t uPciFunNo, const char *pszName)
1648{
1649 PDMDEV_ASSERT_DEVINS(pDevIns);
1650 PVM pVM = pDevIns->Internal.s.pVMR3;
1651 VM_ASSERT_EMT(pVM);
1652 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: pPciDev=%p:{.config={%#.256Rhxs} fFlags=%#x uPciDevNo=%#x uPciFunNo=%#x pszName=%p:{%s}\n",
1653 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->abConfig, fFlags, uPciDevNo, uPciFunNo, pszName, pszName ? pszName : ""));
1654
1655 /*
1656 * Validate input.
1657 */
1658 AssertLogRelMsgReturn(pDevIns->pReg->cMaxPciDevices > 0,
1659 ("'%s'/%d: cMaxPciDevices is 0\n", pDevIns->pReg->szName, pDevIns->iInstance),
1660 VERR_WRONG_ORDER);
1661 AssertLogRelMsgReturn(RT_VALID_PTR(pPciDev),
1662 ("'%s'/%d: Invalid pPciDev value: %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pPciDev),
1663 VERR_INVALID_POINTER);
1664 AssertLogRelMsgReturn(PDMPciDevGetVendorId(pPciDev),
1665 ("'%s'/%d: Vendor ID is not set!\n", pDevIns->pReg->szName, pDevIns->iInstance),
1666 VERR_INVALID_POINTER);
1667 AssertLogRelMsgReturn( uPciDevNo < 32
1668 || uPciDevNo == PDMPCIDEVREG_DEV_NO_FIRST_UNUSED
1669 || uPciDevNo == PDMPCIDEVREG_DEV_NO_SAME_AS_PREV,
1670 ("'%s'/%d: Invalid PCI device number: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, uPciDevNo),
1671 VERR_INVALID_PARAMETER);
1672 AssertLogRelMsgReturn( uPciFunNo < 8
1673 || uPciFunNo == PDMPCIDEVREG_FUN_NO_FIRST_UNUSED,
1674 ("'%s'/%d: Invalid PCI funcion number: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, uPciFunNo),
1675 VERR_INVALID_PARAMETER);
1676 AssertLogRelMsgReturn(!(fFlags & ~PDMPCIDEVREG_F_VALID_MASK),
1677 ("'%s'/%d: Invalid flags: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, fFlags),
1678 VERR_INVALID_FLAGS);
1679 if (!pszName)
1680 pszName = pDevIns->pReg->szName;
1681 AssertLogRelReturn(RT_VALID_PTR(pszName), VERR_INVALID_POINTER);
1682 AssertLogRelReturn(!pPciDev->Int.s.fRegistered, VERR_PDM_NOT_PCI_DEVICE);
1683 AssertLogRelReturn(pPciDev == PDMDEV_GET_PPCIDEV(pDevIns, pPciDev->Int.s.idxSubDev), VERR_PDM_NOT_PCI_DEVICE);
1684 AssertLogRelReturn(pPciDev == PDMDEV_CALC_PPCIDEV(pDevIns, pPciDev->Int.s.idxSubDev), VERR_PDM_NOT_PCI_DEVICE);
1685 AssertMsgReturn(pPciDev->u32Magic == PDMPCIDEV_MAGIC, ("%#x\n", pPciDev->u32Magic), VERR_PDM_NOT_PCI_DEVICE);
1686
1687 /*
1688 * Check the registration order - must be following PDMDEVINSR3::apPciDevs.
1689 */
1690 PPDMPCIDEV const pPrevPciDev = pPciDev->Int.s.idxSubDev == 0 ? NULL
1691 : PDMDEV_GET_PPCIDEV(pDevIns, pPciDev->Int.s.idxSubDev - 1);
1692 if (pPrevPciDev)
1693 {
1694 AssertLogRelReturn(pPrevPciDev->u32Magic == PDMPCIDEV_MAGIC, VERR_INVALID_MAGIC);
1695 AssertLogRelReturn(pPrevPciDev->Int.s.fRegistered, VERR_WRONG_ORDER);
1696 }
1697
1698 /*
1699 * Resolve the PCI configuration node for the device. The default (zero'th)
1700 * is the same as the PDM device, the rest are "PciCfg1..255" CFGM sub-nodes.
1701 */
1702 PCFGMNODE pCfg = pDevIns->Internal.s.pCfgHandle;
1703 if (pPciDev->Int.s.idxSubDev > 0)
1704 pCfg = CFGMR3GetChildF(pDevIns->Internal.s.pCfgHandle, "PciCfg%u", pPciDev->Int.s.idxSubDev);
1705
1706 /*
1707 * We resolve PDMPCIDEVREG_DEV_NO_SAME_AS_PREV, the PCI bus handles
1708 * PDMPCIDEVREG_DEV_NO_FIRST_UNUSED and PDMPCIDEVREG_FUN_NO_FIRST_UNUSED.
1709 */
1710 uint8_t const uPciDevNoRaw = uPciDevNo;
1711 uint32_t uDefPciBusNo = 0;
1712 if (uPciDevNo == PDMPCIDEVREG_DEV_NO_SAME_AS_PREV)
1713 {
1714 if (pPrevPciDev)
1715 {
1716 uPciDevNo = pPrevPciDev->uDevFn >> 3;
1717 uDefPciBusNo = pPrevPciDev->Int.s.idxPdmBus;
1718 }
1719 else
1720 {
1721 /* Look for PCI device registered with an earlier device instance so we can more
1722 easily have multiple functions spanning multiple PDM device instances. */
1723 PPDMDEVINS pPrevIns = pDevIns->Internal.s.pDevR3->pInstances;
1724 for (;;)
1725 {
1726 AssertLogRelMsgReturn(pPrevIns && pPrevIns != pDevIns,
1727 ("'%s'/%d: Can't use PDMPCIDEVREG_DEV_NO_SAME_AS_PREV without a previously registered PCI device by the same or earlier PDM device instance!\n",
1728 pDevIns->pReg->szName, pDevIns->iInstance), VERR_WRONG_ORDER);
1729 if (pPrevIns->Internal.s.pNextR3 == pDevIns)
1730 break;
1731 pPrevIns = pPrevIns->Internal.s.pNextR3;
1732 }
1733
1734 PPDMPCIDEV pOtherPciDev = PDMDEV_GET_PPCIDEV(pPrevIns, 0);
1735 AssertLogRelMsgReturn(pOtherPciDev && pOtherPciDev->Int.s.fRegistered,
1736 ("'%s'/%d: Can't use PDMPCIDEVREG_DEV_NO_SAME_AS_PREV without a previously registered PCI device by the same or earlier PDM device instance!\n",
1737 pDevIns->pReg->szName, pDevIns->iInstance),
1738 VERR_WRONG_ORDER);
1739 for (uint32_t iPrevPciDev = 1; iPrevPciDev < pDevIns->cPciDevs; iPrevPciDev++)
1740 {
1741 PPDMPCIDEV pCur = PDMDEV_GET_PPCIDEV(pPrevIns, iPrevPciDev);
1742 AssertBreak(pCur);
1743 if (!pCur->Int.s.fRegistered)
1744 break;
1745 pOtherPciDev = pCur;
1746 }
1747
1748 uPciDevNo = pOtherPciDev->uDevFn >> 3;
1749 uDefPciBusNo = pOtherPciDev->Int.s.idxPdmBus;
1750 }
1751 }
1752
1753 /*
1754 * Choose the PCI bus for the device.
1755 *
1756 * This is simple. If the device was configured for a particular bus, the PCIBusNo
1757 * configuration value will be set. If not the default bus is 0.
1758 */
1759 /** @cfgm{/Devices/NAME/XX/[PciCfgYY/]PCIBusNo, uint8_t, 0, 7, 0}
1760 * Selects the PCI bus number of a device. The default value isn't necessarily
1761 * zero if the device is registered using PDMPCIDEVREG_DEV_NO_SAME_AS_PREV, it
1762 * will then also inherit the bus number from the previously registered device.
1763 */
1764 uint8_t u8Bus;
1765 int rc = CFGMR3QueryU8Def(pCfg, "PCIBusNo", &u8Bus, (uint8_t)uDefPciBusNo);
1766 AssertLogRelMsgRCReturn(rc, ("Configuration error: PCIBusNo query failed with rc=%Rrc (%s/%d)\n",
1767 rc, pDevIns->pReg->szName, pDevIns->iInstance), rc);
1768 AssertLogRelMsgReturn(u8Bus < RT_ELEMENTS(pVM->pdm.s.aPciBuses),
1769 ("Configuration error: PCIBusNo=%d, max is %d. (%s/%d)\n", u8Bus,
1770 RT_ELEMENTS(pVM->pdm.s.aPciBuses), pDevIns->pReg->szName, pDevIns->iInstance),
1771 VERR_PDM_NO_PCI_BUS);
1772 pPciDev->Int.s.idxPdmBus = u8Bus;
1773 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[u8Bus];
1774 if (pBus->pDevInsR3)
1775 {
1776 /*
1777 * Check the configuration for PCI device and function assignment.
1778 */
1779 /** @cfgm{/Devices/NAME/XX/[PciCfgYY/]PCIDeviceNo, uint8_t, 0, 31}
1780 * Overrides the default PCI device number of a device.
1781 */
1782 uint8_t uCfgDevice;
1783 rc = CFGMR3QueryU8(pCfg, "PCIDeviceNo", &uCfgDevice);
1784 if (RT_SUCCESS(rc))
1785 {
1786 AssertMsgReturn(uCfgDevice <= 31,
1787 ("Configuration error: PCIDeviceNo=%d, max is 31. (%s/%d/%d)\n",
1788 uCfgDevice, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev),
1789 VERR_PDM_BAD_PCI_CONFIG);
1790 uPciDevNo = uCfgDevice;
1791 }
1792 else
1793 AssertMsgReturn(rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT,
1794 ("Configuration error: PCIDeviceNo query failed with rc=%Rrc (%s/%d/%d)\n",
1795 rc, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev),
1796 rc);
1797
1798 /** @cfgm{/Devices/NAME/XX/[PciCfgYY/]PCIFunctionNo, uint8_t, 0, 7}
1799 * Overrides the default PCI function number of a device.
1800 */
1801 uint8_t uCfgFunction;
1802 rc = CFGMR3QueryU8(pCfg, "PCIFunctionNo", &uCfgFunction);
1803 if (RT_SUCCESS(rc))
1804 {
1805 AssertMsgReturn(uCfgFunction <= 7,
1806 ("Configuration error: PCIFunctionNo=%#x, max is 7. (%s/%d/%d)\n",
1807 uCfgFunction, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev),
1808 VERR_PDM_BAD_PCI_CONFIG);
1809 uPciFunNo = uCfgFunction;
1810 }
1811 else
1812 AssertMsgReturn(rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT,
1813 ("Configuration error: PCIFunctionNo query failed with rc=%Rrc (%s/%d/%d)\n",
1814 rc, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev),
1815 rc);
1816
1817
1818 /*
1819 * Initialize the internal data. We only do the wipe and the members
1820 * owned by PDM, the PCI bus does the rest in the registration call.
1821 */
1822 RT_ZERO(pPciDev->Int);
1823
1824 pPciDev->Int.s.idxDevCfg = pPciDev->Int.s.idxSubDev;
1825 pPciDev->Int.s.fReassignableDevNo = uPciDevNoRaw >= VBOX_PCI_MAX_DEVICES;
1826 pPciDev->Int.s.fReassignableFunNo = uPciFunNo >= VBOX_PCI_MAX_FUNCTIONS;
1827 pPciDev->Int.s.pDevInsR3 = pDevIns;
1828 pPciDev->Int.s.idxPdmBus = u8Bus;
1829 pPciDev->Int.s.fRegistered = true;
1830
1831 /* Set some of the public members too. */
1832 pPciDev->pszNameR3 = pszName;
1833
1834 /*
1835 * Call the pci bus device to do the actual registration.
1836 */
1837 pdmLock(pVM);
1838 rc = pBus->pfnRegister(pBus->pDevInsR3, pPciDev, fFlags, uPciDevNo, uPciFunNo, pszName);
1839 pdmUnlock(pVM);
1840 if (RT_SUCCESS(rc))
1841 Log(("PDM: Registered device '%s'/%d as PCI device %d on bus %d\n",
1842 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->uDevFn, pBus->iBus));
1843 else
1844 pPciDev->Int.s.fRegistered = false;
1845 }
1846 else
1847 {
1848 AssertLogRelMsgFailed(("Configuration error: No PCI bus available. This could be related to init order too!\n"));
1849 rc = VERR_PDM_NO_PCI_BUS;
1850 }
1851
1852 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1853 return rc;
1854}
1855
1856
1857/** @interface_method_impl{PDMDEVHLPR3,pfnPCIRegisterMsi} */
1858static DECLCALLBACK(int) pdmR3DevHlp_PCIRegisterMsi(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, PPDMMSIREG pMsiReg)
1859{
1860 PDMDEV_ASSERT_DEVINS(pDevIns);
1861 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1862 pPciDev = pDevIns->apPciDevs[0];
1863 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1864 LogFlow(("pdmR3DevHlp_PCIRegisterMsi: caller='%s'/%d: pPciDev=%p:{%#x} pMsgReg=%p:{cMsiVectors=%d, cMsixVectors=%d}\n",
1865 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, pMsiReg, pMsiReg->cMsiVectors, pMsiReg->cMsixVectors));
1866 PDMPCIDEV_ASSERT_VALID_RET(pDevIns, pPciDev);
1867
1868 AssertLogRelMsgReturn(pDevIns->pReg->cMaxPciDevices > 0,
1869 ("'%s'/%d: cMaxPciDevices is 0\n", pDevIns->pReg->szName, pDevIns->iInstance),
1870 VERR_WRONG_ORDER);
1871 AssertLogRelMsgReturn(pMsiReg->cMsixVectors <= pDevIns->pReg->cMaxMsixVectors,
1872 ("'%s'/%d: cMsixVectors=%u cMaxMsixVectors=%u\n",
1873 pDevIns->pReg->szName, pDevIns->iInstance, pMsiReg->cMsixVectors, pDevIns->pReg->cMaxMsixVectors),
1874 VERR_INVALID_FLAGS);
1875
1876 PVM pVM = pDevIns->Internal.s.pVMR3;
1877 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
1878 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_WRONG_ORDER);
1879 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
1880
1881 pdmLock(pVM);
1882 int rc;
1883 if (pBus->pfnRegisterMsi)
1884 rc = pBus->pfnRegisterMsi(pBus->pDevInsR3, pPciDev, pMsiReg);
1885 else
1886 rc = VERR_NOT_IMPLEMENTED;
1887 pdmUnlock(pVM);
1888
1889 LogFlow(("pdmR3DevHlp_PCIRegisterMsi: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1890 return rc;
1891}
1892
1893
1894/** @interface_method_impl{PDMDEVHLPR3,pfnPCIIORegionRegister} */
1895static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
1896 RTGCPHYS cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
1897{
1898 PDMDEV_ASSERT_DEVINS(pDevIns);
1899 PVM pVM = pDevIns->Internal.s.pVMR3;
1900 VM_ASSERT_EMT(pVM);
1901 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1902 pPciDev = pDevIns->apPciDevs[0];
1903 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1904 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%d cbRegion=%RGp enmType=%d pfnCallback=%p\n",
1905 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iRegion, cbRegion, enmType, pfnCallback));
1906 PDMPCIDEV_ASSERT_VALID_RET(pDevIns, pPciDev);
1907
1908 /*
1909 * Validate input.
1910 */
1911 if (iRegion >= VBOX_PCI_NUM_REGIONS)
1912 {
1913 Assert(iRegion < VBOX_PCI_NUM_REGIONS);
1914 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (iRegion)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1915 return VERR_INVALID_PARAMETER;
1916 }
1917
1918 switch ((int)enmType)
1919 {
1920 case PCI_ADDRESS_SPACE_IO:
1921 /*
1922 * Sanity check: don't allow to register more than 32K of the PCI I/O space.
1923 */
1924 AssertLogRelMsgReturn(cbRegion <= _32K,
1925 ("caller='%s'/%d: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cbRegion),
1926 VERR_INVALID_PARAMETER);
1927 break;
1928
1929 case PCI_ADDRESS_SPACE_MEM:
1930 case PCI_ADDRESS_SPACE_MEM_PREFETCH:
1931 /*
1932 * Sanity check: Don't allow to register more than 2GB of the PCI MMIO space.
1933 */
1934 AssertLogRelMsgReturn(cbRegion <= MM_MMIO_32_MAX,
1935 ("caller='%s'/%d: %RGp (max %RGp)\n",
1936 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, (RTGCPHYS)MM_MMIO_32_MAX),
1937 VERR_OUT_OF_RANGE);
1938 break;
1939
1940 case PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM:
1941 case PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM_PREFETCH:
1942 /*
1943 * Sanity check: Don't allow to register more than 64GB of the 64-bit PCI MMIO space.
1944 */
1945 AssertLogRelMsgReturn(cbRegion <= MM_MMIO_64_MAX,
1946 ("caller='%s'/%d: %RGp (max %RGp)\n",
1947 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, MM_MMIO_64_MAX),
1948 VERR_OUT_OF_RANGE);
1949 break;
1950
1951 default:
1952 AssertMsgFailed(("enmType=%#x is unknown\n", enmType));
1953 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (enmType)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1954 return VERR_INVALID_PARAMETER;
1955 }
1956 if (!pfnCallback)
1957 {
1958 Assert(pfnCallback);
1959 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (callback)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1960 return VERR_INVALID_PARAMETER;
1961 }
1962 AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
1963
1964 /*
1965 * We're currently restricted to page aligned MMIO regions.
1966 */
1967 if ( ((enmType & ~(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM_PREFETCH)) == PCI_ADDRESS_SPACE_MEM)
1968 && cbRegion != RT_ALIGN_64(cbRegion, PAGE_SIZE))
1969 {
1970 Log(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: aligning cbRegion %RGp -> %RGp\n",
1971 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, RT_ALIGN_64(cbRegion, PAGE_SIZE)));
1972 cbRegion = RT_ALIGN_64(cbRegion, PAGE_SIZE);
1973 }
1974
1975 /*
1976 * For registering PCI MMIO memory or PCI I/O memory, the size of the region must be a power of 2!
1977 */
1978 int iLastSet = ASMBitLastSetU64(cbRegion);
1979 Assert(iLastSet > 0);
1980 uint64_t cbRegionAligned = RT_BIT_64(iLastSet - 1);
1981 if (cbRegion > cbRegionAligned)
1982 cbRegion = cbRegionAligned * 2; /* round up */
1983
1984 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
1985 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_WRONG_ORDER);
1986 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
1987
1988 pdmLock(pVM);
1989 int rc = pBus->pfnIORegionRegister(pBus->pDevInsR3, pPciDev, iRegion, cbRegion, enmType, pfnCallback);
1990 pdmUnlock(pVM);
1991
1992 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1993 return rc;
1994}
1995
1996
1997/** @interface_method_impl{PDMDEVHLPR3,pfnPCIInterceptConfigAccesses} */
1998static DECLCALLBACK(int) pdmR3DevHlp_PCIInterceptConfigAccesses(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
1999 PFNPCICONFIGREAD pfnRead, PFNPCICONFIGWRITE pfnWrite)
2000{
2001 PDMDEV_ASSERT_DEVINS(pDevIns);
2002 PVM pVM = pDevIns->Internal.s.pVMR3;
2003 VM_ASSERT_EMT(pVM);
2004 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2005 pPciDev = pDevIns->apPciDevs[0];
2006 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2007 LogFlow(("pdmR3DevHlp_PCIInterceptConfigAccesses: caller='%s'/%d: pPciDev=%p pfnRead=%p pfnWrite=%p\n",
2008 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pfnRead, pfnWrite));
2009 PDMPCIDEV_ASSERT_VALID_RET(pDevIns, pPciDev);
2010
2011 /*
2012 * Validate input.
2013 */
2014 AssertPtr(pfnRead);
2015 AssertPtr(pfnWrite);
2016 AssertPtr(pPciDev);
2017
2018 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2019 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_INTERNAL_ERROR_2);
2020 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2021 AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
2022
2023 /*
2024 * Do the job.
2025 */
2026 pdmLock(pVM);
2027 pBus->pfnInterceptConfigAccesses(pBus->pDevInsR3, pPciDev, pfnRead, pfnWrite);
2028 pdmUnlock(pVM);
2029
2030 LogFlow(("pdmR3DevHlp_PCIInterceptConfigAccesses: caller='%s'/%d: returns VINF_SUCCESS\n",
2031 pDevIns->pReg->szName, pDevIns->iInstance));
2032 return VINF_SUCCESS;
2033}
2034
2035
2036/** @interface_method_impl{PDMDEVHLPR3,pfnPCIConfigWrite} */
2037static DECLCALLBACK(VBOXSTRICTRC)
2038pdmR3DevHlp_PCIConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, unsigned cb, uint32_t u32Value)
2039{
2040 PDMDEV_ASSERT_DEVINS(pDevIns);
2041 PVM pVM = pDevIns->Internal.s.pVMR3;
2042 AssertPtrReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2043 LogFlow(("pdmR3DevHlp_PCIConfigWrite: caller='%s'/%d: pPciDev=%p uAddress=%#x cd=%d u32Value=%#x\n",
2044 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, uAddress, cb, u32Value));
2045
2046 /*
2047 * Resolve the bus.
2048 */
2049 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2050 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_INTERNAL_ERROR_2);
2051 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2052
2053 /*
2054 * Do the job.
2055 */
2056 VBOXSTRICTRC rcStrict = pBus->pfnConfigWrite(pBus->pDevInsR3, pPciDev, uAddress, cb, u32Value);
2057
2058 LogFlow(("pdmR3DevHlp_PCIConfigWrite: caller='%s'/%d: returns %Rrc\n",
2059 pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict)));
2060 return rcStrict;
2061}
2062
2063
2064/** @interface_method_impl{PDMDEVHLPR3,pfnPCIConfigRead} */
2065static DECLCALLBACK(VBOXSTRICTRC)
2066pdmR3DevHlp_PCIConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, unsigned cb, uint32_t *pu32Value)
2067{
2068 PDMDEV_ASSERT_DEVINS(pDevIns);
2069 PVM pVM = pDevIns->Internal.s.pVMR3;
2070 AssertPtrReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2071 LogFlow(("pdmR3DevHlp_PCIConfigRead: caller='%s'/%d: pPciDev=%p uAddress=%#x cd=%d pu32Value=%p:{%#x}\n",
2072 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, uAddress, cb, pu32Value, *pu32Value));
2073
2074 /*
2075 * Resolve the bus.
2076 */
2077 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2078 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_INTERNAL_ERROR_2);
2079 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2080
2081 /*
2082 * Do the job.
2083 */
2084 VBOXSTRICTRC rcStrict = pBus->pfnConfigRead(pBus->pDevInsR3, pPciDev, uAddress, cb, pu32Value);
2085
2086 LogFlow(("pdmR3DevHlp_PCIConfigRead: caller='%s'/%d: returns %Rrc (*pu32Value=%#x)\n",
2087 pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict), *pu32Value));
2088 return rcStrict;
2089}
2090
2091
2092/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysRead} */
2093static DECLCALLBACK(int)
2094pdmR3DevHlp_PCIPhysRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
2095{
2096 PDMDEV_ASSERT_DEVINS(pDevIns);
2097 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2098 pPciDev = pDevIns->apPciDevs[0];
2099 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2100 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
2101
2102#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
2103 /*
2104 * Just check the busmaster setting here and forward the request to the generic read helper.
2105 */
2106 if (PCIDevIsBusmaster(pPciDev))
2107 { /* likely */ }
2108 else
2109 {
2110 Log(("pdmR3DevHlp_PCIPhysRead: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbRead=%#zx\n",
2111 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbRead));
2112 memset(pvBuf, 0xff, cbRead);
2113 return VERR_PDM_NOT_PCI_BUS_MASTER;
2114 }
2115#endif
2116
2117 return pDevIns->pHlpR3->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead);
2118}
2119
2120
2121/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysWrite} */
2122static DECLCALLBACK(int)
2123pdmR3DevHlp_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
2124{
2125 PDMDEV_ASSERT_DEVINS(pDevIns);
2126 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2127 pPciDev = pDevIns->apPciDevs[0];
2128 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2129 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
2130
2131#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
2132 /*
2133 * Just check the busmaster setting here and forward the request to the generic read helper.
2134 */
2135 if (PCIDevIsBusmaster(pPciDev))
2136 { /* likely */ }
2137 else
2138 {
2139 Log(("pdmR3DevHlp_PCIPhysWrite: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n",
2140 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
2141 return VERR_PDM_NOT_PCI_BUS_MASTER;
2142 }
2143#endif
2144
2145 return pDevIns->pHlpR3->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite);
2146}
2147
2148
2149/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrq} */
2150static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
2151{
2152 PDMDEV_ASSERT_DEVINS(pDevIns);
2153 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2154 pPciDev = pDevIns->apPciDevs[0];
2155 AssertReturnVoid(pPciDev);
2156 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
2157 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
2158 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
2159
2160 /*
2161 * Validate input.
2162 */
2163 Assert(iIrq == 0);
2164 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
2165
2166 /*
2167 * Must have a PCI device registered!
2168 */
2169 PVM pVM = pDevIns->Internal.s.pVMR3;
2170 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2171 AssertReturnVoid(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
2172 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2173
2174 pdmLock(pVM);
2175 uint32_t uTagSrc;
2176 if (iLevel & PDM_IRQ_LEVEL_HIGH)
2177 {
2178 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
2179 if (iLevel == PDM_IRQ_LEVEL_HIGH)
2180 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2181 else
2182 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2183 }
2184 else
2185 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
2186
2187 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel, uTagSrc);
2188
2189 if (iLevel == PDM_IRQ_LEVEL_LOW)
2190 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2191 pdmUnlock(pVM);
2192
2193 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
2194}
2195
2196
2197/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrqNoWait} */
2198static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
2199{
2200 pdmR3DevHlp_PCISetIrq(pDevIns, pPciDev, iIrq, iLevel);
2201}
2202
2203
2204/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrq} */
2205static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
2206{
2207 PDMDEV_ASSERT_DEVINS(pDevIns);
2208 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
2209
2210 /*
2211 * Validate input.
2212 */
2213 Assert(iIrq < 16);
2214 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
2215
2216 PVM pVM = pDevIns->Internal.s.pVMR3;
2217
2218 /*
2219 * Do the job.
2220 */
2221 pdmLock(pVM);
2222 uint32_t uTagSrc;
2223 if (iLevel & PDM_IRQ_LEVEL_HIGH)
2224 {
2225 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
2226 if (iLevel == PDM_IRQ_LEVEL_HIGH)
2227 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2228 else
2229 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2230 }
2231 else
2232 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
2233
2234 PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */
2235
2236 if (iLevel == PDM_IRQ_LEVEL_LOW)
2237 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2238 pdmUnlock(pVM);
2239
2240 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
2241}
2242
2243
2244/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrqNoWait} */
2245static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
2246{
2247 pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
2248}
2249
2250
2251/** @interface_method_impl{PDMDEVHLPR3,pfnIoApicSendMsi} */
2252static DECLCALLBACK(void) pdmR3DevHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue)
2253{
2254 PDMDEV_ASSERT_DEVINS(pDevIns);
2255 LogFlow(("pdmR3DevHlp_IoApicSendMsi: caller='%s'/%d: GCPhys=%RGp uValue=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, uValue));
2256
2257 /*
2258 * Validate input.
2259 */
2260 Assert(GCPhys != 0);
2261 Assert(uValue != 0);
2262
2263 PVM pVM = pDevIns->Internal.s.pVMR3;
2264
2265 /*
2266 * Do the job.
2267 */
2268 pdmLock(pVM);
2269 uint32_t uTagSrc;
2270 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
2271 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2272
2273 PDMIoApicSendMsi(pVM, GCPhys, uValue, uTagSrc); /* (The API takes the lock recursively.) */
2274
2275 pdmUnlock(pVM);
2276
2277 LogFlow(("pdmR3DevHlp_IoApicSendMsi: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
2278}
2279
2280
2281/** @interface_method_impl{PDMDEVHLPR3,pfnDriverAttach} */
2282static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
2283{
2284 PDMDEV_ASSERT_DEVINS(pDevIns);
2285 PVM pVM = pDevIns->Internal.s.pVMR3;
2286 VM_ASSERT_EMT(pVM);
2287 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
2288 pDevIns->pReg->szName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
2289
2290 /*
2291 * Lookup the LUN, it might already be registered.
2292 */
2293 PPDMLUN pLunPrev = NULL;
2294 PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;
2295 for (; pLun; pLunPrev = pLun, pLun = pLun->pNext)
2296 if (pLun->iLun == iLun)
2297 break;
2298
2299 /*
2300 * Create the LUN if if wasn't found, else check if driver is already attached to it.
2301 */
2302 if (!pLun)
2303 {
2304 if ( !pBaseInterface
2305 || !pszDesc
2306 || !*pszDesc)
2307 {
2308 Assert(pBaseInterface);
2309 Assert(pszDesc || *pszDesc);
2310 return VERR_INVALID_PARAMETER;
2311 }
2312
2313 pLun = (PPDMLUN)MMR3HeapAlloc(pVM, MM_TAG_PDM_LUN, sizeof(*pLun));
2314 if (!pLun)
2315 return VERR_NO_MEMORY;
2316
2317 pLun->iLun = iLun;
2318 pLun->pNext = pLunPrev ? pLunPrev->pNext : NULL;
2319 pLun->pTop = NULL;
2320 pLun->pBottom = NULL;
2321 pLun->pDevIns = pDevIns;
2322 pLun->pUsbIns = NULL;
2323 pLun->pszDesc = pszDesc;
2324 pLun->pBase = pBaseInterface;
2325 if (!pLunPrev)
2326 pDevIns->Internal.s.pLunsR3 = pLun;
2327 else
2328 pLunPrev->pNext = pLun;
2329 Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
2330 iLun, pszDesc, pDevIns->pReg->szName, pDevIns->iInstance));
2331 }
2332 else if (pLun->pTop)
2333 {
2334 AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
2335 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
2336 return VERR_PDM_DRIVER_ALREADY_ATTACHED;
2337 }
2338 Assert(pLun->pBase == pBaseInterface);
2339
2340
2341 /*
2342 * Get the attached driver configuration.
2343 */
2344 int rc;
2345 PCFGMNODE pNode = CFGMR3GetChildF(pDevIns->Internal.s.pCfgHandle, "LUN#%u", iLun);
2346 if (pNode)
2347 rc = pdmR3DrvInstantiate(pVM, pNode, pBaseInterface, NULL /*pDrvAbove*/, pLun, ppBaseInterface);
2348 else
2349 rc = VERR_PDM_NO_ATTACHED_DRIVER;
2350
2351 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2352 return rc;
2353}
2354
2355
2356/** @interface_method_impl{PDMDEVHLPR3,pfnDriverDetach} */
2357static DECLCALLBACK(int) pdmR3DevHlp_DriverDetach(PPDMDEVINS pDevIns, PPDMDRVINS pDrvIns, uint32_t fFlags)
2358{
2359 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
2360 LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: pDrvIns=%p\n",
2361 pDevIns->pReg->szName, pDevIns->iInstance, pDrvIns));
2362
2363#ifdef VBOX_STRICT
2364 PVM pVM = pDevIns->Internal.s.pVMR3;
2365 VM_ASSERT_EMT(pVM);
2366#endif
2367
2368 int rc = pdmR3DrvDetach(pDrvIns, fFlags);
2369
2370 LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2371 return rc;
2372}
2373
2374
2375/** @interface_method_impl{PDMDEVHLPR3,pfnQueueCreate} */
2376static DECLCALLBACK(int) pdmR3DevHlp_QueueCreate(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
2377 PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue)
2378{
2379 PDMDEV_ASSERT_DEVINS(pDevIns);
2380 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fRZEnabled=%RTbool pszName=%p:{%s} ppQueue=%p\n",
2381 pDevIns->pReg->szName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, pszName, ppQueue));
2382
2383 PVM pVM = pDevIns->Internal.s.pVMR3;
2384 VM_ASSERT_EMT(pVM);
2385
2386 if (pDevIns->iInstance > 0)
2387 {
2388 pszName = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s_%u", pszName, pDevIns->iInstance);
2389 AssertLogRelReturn(pszName, VERR_NO_MEMORY);
2390 }
2391
2392 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, ppQueue);
2393
2394 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *ppQueue));
2395 return rc;
2396}
2397
2398
2399/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectInit} */
2400static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
2401 const char *pszNameFmt, va_list va)
2402{
2403 PDMDEV_ASSERT_DEVINS(pDevIns);
2404 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszNameFmt=%p:{%s}\n",
2405 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pszNameFmt, pszNameFmt));
2406
2407 PVM pVM = pDevIns->Internal.s.pVMR3;
2408 VM_ASSERT_EMT(pVM);
2409 int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
2410
2411 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2412 return rc;
2413}
2414
2415
2416/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNop} */
2417static DECLCALLBACK(PPDMCRITSECT) pdmR3DevHlp_CritSectGetNop(PPDMDEVINS pDevIns)
2418{
2419 PDMDEV_ASSERT_DEVINS(pDevIns);
2420 PVM pVM = pDevIns->Internal.s.pVMR3;
2421 VM_ASSERT_EMT(pVM);
2422
2423 PPDMCRITSECT pCritSect = PDMR3CritSectGetNop(pVM);
2424 LogFlow(("pdmR3DevHlp_CritSectGetNop: caller='%s'/%d: return %p\n",
2425 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2426 return pCritSect;
2427}
2428
2429
2430/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopR0} */
2431static DECLCALLBACK(R0PTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopR0(PPDMDEVINS pDevIns)
2432{
2433 PDMDEV_ASSERT_DEVINS(pDevIns);
2434 PVM pVM = pDevIns->Internal.s.pVMR3;
2435 VM_ASSERT_EMT(pVM);
2436
2437 R0PTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopR0(pVM);
2438 LogFlow(("pdmR3DevHlp_CritSectGetNopR0: caller='%s'/%d: return %RHv\n",
2439 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2440 return pCritSect;
2441}
2442
2443
2444/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopRC} */
2445static DECLCALLBACK(RCPTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopRC(PPDMDEVINS pDevIns)
2446{
2447 PDMDEV_ASSERT_DEVINS(pDevIns);
2448 PVM pVM = pDevIns->Internal.s.pVMR3;
2449 VM_ASSERT_EMT(pVM);
2450
2451 RCPTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopRC(pVM);
2452 LogFlow(("pdmR3DevHlp_CritSectGetNopRC: caller='%s'/%d: return %RRv\n",
2453 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2454 return pCritSect;
2455}
2456
2457
2458/** @interface_method_impl{PDMDEVHLPR3,pfnSetDeviceCritSect} */
2459static DECLCALLBACK(int) pdmR3DevHlp_SetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2460{
2461 /*
2462 * Validate input.
2463 *
2464 * Note! We only allow the automatically created default critical section
2465 * to be replaced by this API.
2466 */
2467 PDMDEV_ASSERT_DEVINS(pDevIns);
2468 AssertPtrReturn(pCritSect, VERR_INVALID_POINTER);
2469 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: pCritSect=%p (%s)\n",
2470 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pCritSect->s.pszName));
2471 AssertReturn(PDMCritSectIsInitialized(pCritSect), VERR_INVALID_PARAMETER);
2472 PVM pVM = pDevIns->Internal.s.pVMR3;
2473 AssertReturn(pCritSect->s.pVMR3 == pVM, VERR_INVALID_PARAMETER);
2474
2475 VM_ASSERT_EMT(pVM);
2476 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
2477
2478 AssertReturn(pDevIns->pCritSectRoR3, VERR_PDM_DEV_IPE_1);
2479 AssertReturn(pDevIns->pCritSectRoR3->s.fAutomaticDefaultCritsect, VERR_WRONG_ORDER);
2480 AssertReturn(!pDevIns->pCritSectRoR3->s.fUsedByTimerOrSimilar, VERR_WRONG_ORDER);
2481 AssertReturn(pDevIns->pCritSectRoR3 != pCritSect, VERR_INVALID_PARAMETER);
2482
2483 /*
2484 * Replace the critical section and destroy the automatic default section.
2485 */
2486 PPDMCRITSECT pOldCritSect = pDevIns->pCritSectRoR3;
2487 pDevIns->pCritSectRoR3 = pCritSect;
2488 pDevIns->Internal.s.fIntFlags |= PDMDEVINSINT_FLAGS_CHANGED_CRITSECT;
2489
2490 Assert(RT_BOOL(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED) == pDevIns->fR0Enabled);
2491 if ( (pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED)
2492 && !(pDevIns->Internal.s.pDevR3->pReg->fFlags & PDM_DEVREG_FLAGS_NEW_STYLE))
2493 {
2494 PDMDEVICECOMPATSETCRITSECTREQ Req;
2495 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
2496 Req.Hdr.cbReq = sizeof(Req);
2497 Req.idxR0Device = pDevIns->Internal.s.idxR0Device;
2498 Req.pDevInsR3 = pDevIns;
2499 Req.pCritSectR3 = pCritSect;
2500 int rc = VMMR3CallR0(pVM, VMMR0_DO_PDM_DEVICE_COMPAT_SET_CRITSECT, 0, &Req.Hdr);
2501 AssertLogRelRCReturn(rc, rc);
2502 }
2503
2504 PDMR3CritSectDelete(pOldCritSect);
2505 Assert((uintptr_t)pOldCritSect - (uintptr_t)pDevIns < pDevIns->cbRing3);
2506
2507 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
2508 return VINF_SUCCESS;
2509}
2510
2511
2512/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectYield} */
2513static DECLCALLBACK(bool) pdmR3DevHlp_CritSectYield(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2514{
2515 PDMDEV_ASSERT_DEVINS(pDevIns);
2516 return PDMR3CritSectYield(pDevIns->Internal.s.pVMR3, pCritSect);
2517}
2518
2519
2520/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnter} */
2521static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy)
2522{
2523 PDMDEV_ASSERT_DEVINS(pDevIns);
2524 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2525 return PDMCritSectEnter(pCritSect, rcBusy);
2526}
2527
2528
2529/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnterDebug} */
2530static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
2531{
2532 PDMDEV_ASSERT_DEVINS(pDevIns);
2533 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2534 return PDMCritSectEnterDebug(pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
2535}
2536
2537
2538/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnter} */
2539static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2540{
2541 PDMDEV_ASSERT_DEVINS(pDevIns);
2542 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2543 return PDMCritSectTryEnter(pCritSect);
2544}
2545
2546
2547/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnterDebug} */
2548static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
2549{
2550 PDMDEV_ASSERT_DEVINS(pDevIns);
2551 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2552 return PDMCritSectTryEnterDebug(pCritSect, uId, RT_SRC_POS_ARGS);
2553}
2554
2555
2556/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectLeave} */
2557static DECLCALLBACK(int) pdmR3DevHlp_CritSectLeave(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2558{
2559 PDMDEV_ASSERT_DEVINS(pDevIns);
2560 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2561 return PDMCritSectLeave(pCritSect);
2562}
2563
2564
2565/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsOwner} */
2566static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsOwner(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2567{
2568 PDMDEV_ASSERT_DEVINS(pDevIns);
2569 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2570 return PDMCritSectIsOwner(pCritSect);
2571}
2572
2573
2574/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsInitialized} */
2575static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsInitialized(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2576{
2577 PDMDEV_ASSERT_DEVINS(pDevIns);
2578 RT_NOREF(pDevIns);
2579 return PDMCritSectIsInitialized(pCritSect);
2580}
2581
2582
2583/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectHasWaiters} */
2584static DECLCALLBACK(bool) pdmR3DevHlp_CritSectHasWaiters(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2585{
2586 PDMDEV_ASSERT_DEVINS(pDevIns);
2587 RT_NOREF(pDevIns);
2588 return PDMCritSectHasWaiters(pCritSect);
2589}
2590
2591
2592/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetRecursion} */
2593static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectGetRecursion(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2594{
2595 PDMDEV_ASSERT_DEVINS(pDevIns);
2596 RT_NOREF(pDevIns);
2597 return PDMCritSectGetRecursion(pCritSect);
2598}
2599
2600
2601/** @interface_method_impl{PDMDEVHLPR3,pfnThreadCreate} */
2602static DECLCALLBACK(int) pdmR3DevHlp_ThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
2603 PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
2604{
2605 PDMDEV_ASSERT_DEVINS(pDevIns);
2606 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2607 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
2608 pDevIns->pReg->szName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
2609
2610 int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
2611
2612 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDevIns->pReg->szName, pDevIns->iInstance,
2613 rc, *ppThread));
2614 return rc;
2615}
2616
2617
2618/** @interface_method_impl{PDMDEVHLPR3,pfnSetAsyncNotification} */
2619static DECLCALLBACK(int) pdmR3DevHlp_SetAsyncNotification(PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)
2620{
2621 PDMDEV_ASSERT_DEVINS(pDevIns);
2622 VM_ASSERT_EMT0(pDevIns->Internal.s.pVMR3);
2623 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: pfnAsyncNotify=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pfnAsyncNotify));
2624
2625 int rc = VINF_SUCCESS;
2626 AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
2627 AssertStmt(!pDevIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
2628 AssertStmt(pDevIns->Internal.s.fIntFlags & (PDMDEVINSINT_FLAGS_SUSPENDED | PDMDEVINSINT_FLAGS_RESET), rc = VERR_WRONG_ORDER);
2629 VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
2630 AssertStmt( enmVMState == VMSTATE_SUSPENDING
2631 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
2632 || enmVMState == VMSTATE_SUSPENDING_LS
2633 || enmVMState == VMSTATE_RESETTING
2634 || enmVMState == VMSTATE_RESETTING_LS
2635 || enmVMState == VMSTATE_POWERING_OFF
2636 || enmVMState == VMSTATE_POWERING_OFF_LS,
2637 rc = VERR_INVALID_STATE);
2638
2639 if (RT_SUCCESS(rc))
2640 pDevIns->Internal.s.pfnAsyncNotify = pfnAsyncNotify;
2641
2642 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2643 return rc;
2644}
2645
2646
2647/** @interface_method_impl{PDMDEVHLPR3,pfnAsyncNotificationCompleted} */
2648static DECLCALLBACK(void) pdmR3DevHlp_AsyncNotificationCompleted(PPDMDEVINS pDevIns)
2649{
2650 PDMDEV_ASSERT_DEVINS(pDevIns);
2651 PVM pVM = pDevIns->Internal.s.pVMR3;
2652
2653 VMSTATE enmVMState = VMR3GetState(pVM);
2654 if ( enmVMState == VMSTATE_SUSPENDING
2655 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
2656 || enmVMState == VMSTATE_SUSPENDING_LS
2657 || enmVMState == VMSTATE_RESETTING
2658 || enmVMState == VMSTATE_RESETTING_LS
2659 || enmVMState == VMSTATE_POWERING_OFF
2660 || enmVMState == VMSTATE_POWERING_OFF_LS)
2661 {
2662 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2663 VMR3AsyncPdmNotificationWakeupU(pVM->pUVM);
2664 }
2665 else
2666 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d: enmVMState=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, enmVMState));
2667}
2668
2669
2670/** @interface_method_impl{PDMDEVHLPR3,pfnRTCRegister} */
2671static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
2672{
2673 PDMDEV_ASSERT_DEVINS(pDevIns);
2674 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2675 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
2676 pDevIns->pReg->szName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
2677 pRtcReg->pfnWrite, ppRtcHlp));
2678
2679 /*
2680 * Validate input.
2681 */
2682 if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
2683 {
2684 AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
2685 PDM_RTCREG_VERSION));
2686 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (version)\n",
2687 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2688 return VERR_INVALID_PARAMETER;
2689 }
2690 if ( !pRtcReg->pfnWrite
2691 || !pRtcReg->pfnRead)
2692 {
2693 Assert(pRtcReg->pfnWrite);
2694 Assert(pRtcReg->pfnRead);
2695 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
2696 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2697 return VERR_INVALID_PARAMETER;
2698 }
2699
2700 if (!ppRtcHlp)
2701 {
2702 Assert(ppRtcHlp);
2703 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (ppRtcHlp)\n",
2704 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2705 return VERR_INVALID_PARAMETER;
2706 }
2707
2708 /*
2709 * Only one DMA device.
2710 */
2711 PVM pVM = pDevIns->Internal.s.pVMR3;
2712 if (pVM->pdm.s.pRtc)
2713 {
2714 AssertMsgFailed(("Only one RTC device is supported!\n"));
2715 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
2716 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2717 return VERR_INVALID_PARAMETER;
2718 }
2719
2720 /*
2721 * Allocate and initialize pci bus structure.
2722 */
2723 int rc = VINF_SUCCESS;
2724 PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
2725 if (pRtc)
2726 {
2727 pRtc->pDevIns = pDevIns;
2728 pRtc->Reg = *pRtcReg;
2729 pVM->pdm.s.pRtc = pRtc;
2730
2731 /* set the helper pointer. */
2732 *ppRtcHlp = &g_pdmR3DevRtcHlp;
2733 Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
2734 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
2735 }
2736 else
2737 rc = VERR_NO_MEMORY;
2738
2739 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
2740 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2741 return rc;
2742}
2743
2744
2745/** @interface_method_impl{PDMDEVHLPR3,pfnDMARegister} */
2746static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
2747{
2748 PDMDEV_ASSERT_DEVINS(pDevIns);
2749 PVM pVM = pDevIns->Internal.s.pVMR3;
2750 VM_ASSERT_EMT(pVM);
2751 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
2752 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
2753 int rc = VINF_SUCCESS;
2754 if (pVM->pdm.s.pDmac)
2755 pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
2756 else
2757 {
2758 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2759 rc = VERR_PDM_NO_DMAC_INSTANCE;
2760 }
2761 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Rrc\n",
2762 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2763 return rc;
2764}
2765
2766
2767/** @interface_method_impl{PDMDEVHLPR3,pfnDMAReadMemory} */
2768static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
2769{
2770 PDMDEV_ASSERT_DEVINS(pDevIns);
2771 PVM pVM = pDevIns->Internal.s.pVMR3;
2772 VM_ASSERT_EMT(pVM);
2773 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
2774 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
2775 int rc = VINF_SUCCESS;
2776 if (pVM->pdm.s.pDmac)
2777 {
2778 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
2779 if (pcbRead)
2780 *pcbRead = cb;
2781 }
2782 else
2783 {
2784 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2785 rc = VERR_PDM_NO_DMAC_INSTANCE;
2786 }
2787 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Rrc\n",
2788 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2789 return rc;
2790}
2791
2792
2793/** @interface_method_impl{PDMDEVHLPR3,pfnDMAWriteMemory} */
2794static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
2795{
2796 PDMDEV_ASSERT_DEVINS(pDevIns);
2797 PVM pVM = pDevIns->Internal.s.pVMR3;
2798 VM_ASSERT_EMT(pVM);
2799 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
2800 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
2801 int rc = VINF_SUCCESS;
2802 if (pVM->pdm.s.pDmac)
2803 {
2804 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
2805 if (pcbWritten)
2806 *pcbWritten = cb;
2807 }
2808 else
2809 {
2810 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2811 rc = VERR_PDM_NO_DMAC_INSTANCE;
2812 }
2813 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Rrc\n",
2814 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2815 return rc;
2816}
2817
2818
2819/** @interface_method_impl{PDMDEVHLPR3,pfnDMASetDREQ} */
2820static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
2821{
2822 PDMDEV_ASSERT_DEVINS(pDevIns);
2823 PVM pVM = pDevIns->Internal.s.pVMR3;
2824 VM_ASSERT_EMT(pVM);
2825 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
2826 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, uLevel));
2827 int rc = VINF_SUCCESS;
2828 if (pVM->pdm.s.pDmac)
2829 pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
2830 else
2831 {
2832 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2833 rc = VERR_PDM_NO_DMAC_INSTANCE;
2834 }
2835 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Rrc\n",
2836 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2837 return rc;
2838}
2839
2840/** @interface_method_impl{PDMDEVHLPR3,pfnDMAGetChannelMode} */
2841static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
2842{
2843 PDMDEV_ASSERT_DEVINS(pDevIns);
2844 PVM pVM = pDevIns->Internal.s.pVMR3;
2845 VM_ASSERT_EMT(pVM);
2846 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
2847 pDevIns->pReg->szName, pDevIns->iInstance, uChannel));
2848 uint8_t u8Mode;
2849 if (pVM->pdm.s.pDmac)
2850 u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
2851 else
2852 {
2853 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2854 u8Mode = 3 << 2 /* illegal mode type */;
2855 }
2856 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
2857 pDevIns->pReg->szName, pDevIns->iInstance, u8Mode));
2858 return u8Mode;
2859}
2860
2861/** @interface_method_impl{PDMDEVHLPR3,pfnDMASchedule} */
2862static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
2863{
2864 PDMDEV_ASSERT_DEVINS(pDevIns);
2865 PVM pVM = pDevIns->Internal.s.pVMR3;
2866 VM_ASSERT_EMT(pVM);
2867 LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
2868 pDevIns->pReg->szName, pDevIns->iInstance, VM_FF_IS_SET(pVM, VM_FF_PDM_DMA)));
2869
2870 AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2871 VM_FF_SET(pVM, VM_FF_PDM_DMA);
2872#ifdef VBOX_WITH_REM
2873 REMR3NotifyDmaPending(pVM);
2874#endif
2875 VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
2876}
2877
2878
2879/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSWrite} */
2880static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
2881{
2882 PDMDEV_ASSERT_DEVINS(pDevIns);
2883 PVM pVM = pDevIns->Internal.s.pVMR3;
2884 VM_ASSERT_EMT(pVM);
2885
2886 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
2887 pDevIns->pReg->szName, pDevIns->iInstance, iReg, u8Value));
2888 int rc;
2889 if (pVM->pdm.s.pRtc)
2890 {
2891 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
2892 rc = PDMCritSectEnter(pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
2893 if (RT_SUCCESS(rc))
2894 {
2895 rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pDevInsRtc, iReg, u8Value);
2896 PDMCritSectLeave(pDevInsRtc->pCritSectRoR3);
2897 }
2898 }
2899 else
2900 rc = VERR_PDM_NO_RTC_INSTANCE;
2901
2902 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
2903 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2904 return rc;
2905}
2906
2907
2908/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSRead} */
2909static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
2910{
2911 PDMDEV_ASSERT_DEVINS(pDevIns);
2912 PVM pVM = pDevIns->Internal.s.pVMR3;
2913 VM_ASSERT_EMT(pVM);
2914
2915 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
2916 pDevIns->pReg->szName, pDevIns->iInstance, iReg, pu8Value));
2917 int rc;
2918 if (pVM->pdm.s.pRtc)
2919 {
2920 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
2921 rc = PDMCritSectEnter(pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
2922 if (RT_SUCCESS(rc))
2923 {
2924 rc = pVM->pdm.s.pRtc->Reg.pfnRead(pDevInsRtc, iReg, pu8Value);
2925 PDMCritSectLeave(pDevInsRtc->pCritSectRoR3);
2926 }
2927 }
2928 else
2929 rc = VERR_PDM_NO_RTC_INSTANCE;
2930
2931 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
2932 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2933 return rc;
2934}
2935
2936
2937/** @interface_method_impl{PDMDEVHLPR3,pfnAssertEMT} */
2938static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
2939{
2940 PDMDEV_ASSERT_DEVINS(pDevIns);
2941 if (VM_IS_EMT(pDevIns->Internal.s.pVMR3))
2942 return true;
2943
2944 char szMsg[100];
2945 RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
2946 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
2947 AssertBreakpoint();
2948 return false;
2949}
2950
2951
2952/** @interface_method_impl{PDMDEVHLPR3,pfnAssertOther} */
2953static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
2954{
2955 PDMDEV_ASSERT_DEVINS(pDevIns);
2956 if (!VM_IS_EMT(pDevIns->Internal.s.pVMR3))
2957 return true;
2958
2959 char szMsg[100];
2960 RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
2961 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
2962 AssertBreakpoint();
2963 return false;
2964}
2965
2966
2967/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetRCInterfaceSymbols} */
2968static DECLCALLBACK(int) pdmR3DevHlp_LdrGetRCInterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
2969 const char *pszSymPrefix, const char *pszSymList)
2970{
2971 PDMDEV_ASSERT_DEVINS(pDevIns);
2972 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2973 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
2974 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
2975
2976 int rc;
2977 if ( strncmp(pszSymPrefix, "dev", 3) == 0
2978 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
2979 {
2980 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
2981 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
2982 pvInterface, cbInterface,
2983 pDevIns->pReg->pszRCMod, pDevIns->Internal.s.pDevR3->pszRCSearchPath,
2984 pszSymPrefix, pszSymList,
2985 false /*fRing0OrRC*/);
2986 else
2987 {
2988 AssertMsgFailed(("Not a raw-mode enabled driver\n"));
2989 rc = VERR_PERMISSION_DENIED;
2990 }
2991 }
2992 else
2993 {
2994 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
2995 pszSymPrefix, pDevIns->pReg->szName));
2996 rc = VERR_INVALID_NAME;
2997 }
2998
2999 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3000 pDevIns->iInstance, rc));
3001 return rc;
3002}
3003
3004
3005/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetR0InterfaceSymbols} */
3006static DECLCALLBACK(int) pdmR3DevHlp_LdrGetR0InterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
3007 const char *pszSymPrefix, const char *pszSymList)
3008{
3009 PDMDEV_ASSERT_DEVINS(pDevIns);
3010 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3011 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
3012 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
3013
3014 int rc;
3015 if ( strncmp(pszSymPrefix, "dev", 3) == 0
3016 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
3017 {
3018 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3019 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
3020 pvInterface, cbInterface,
3021 pDevIns->pReg->pszR0Mod, pDevIns->Internal.s.pDevR3->pszR0SearchPath,
3022 pszSymPrefix, pszSymList,
3023 true /*fRing0OrRC*/);
3024 else
3025 {
3026 AssertMsgFailed(("Not a ring-0 enabled driver\n"));
3027 rc = VERR_PERMISSION_DENIED;
3028 }
3029 }
3030 else
3031 {
3032 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
3033 pszSymPrefix, pDevIns->pReg->szName));
3034 rc = VERR_INVALID_NAME;
3035 }
3036
3037 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3038 pDevIns->iInstance, rc));
3039 return rc;
3040}
3041
3042
3043/** @interface_method_impl{PDMDEVHLPR3,pfnCallR0} */
3044static DECLCALLBACK(int) pdmR3DevHlp_CallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
3045{
3046 PDMDEV_ASSERT_DEVINS(pDevIns);
3047 PVM pVM = pDevIns->Internal.s.pVMR3;
3048 VM_ASSERT_EMT(pVM);
3049 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: uOperation=%#x u64Arg=%#RX64\n",
3050 pDevIns->pReg->szName, pDevIns->iInstance, uOperation, u64Arg));
3051
3052 /*
3053 * Resolve the ring-0 entry point. There is not need to remember this like
3054 * we do for drivers since this is mainly for construction time hacks and
3055 * other things that aren't performance critical.
3056 */
3057 int rc;
3058 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3059 {
3060 char szSymbol[ sizeof("devR0") + sizeof(pDevIns->pReg->szName) + sizeof("ReqHandler")];
3061 strcat(strcat(strcpy(szSymbol, "devR0"), pDevIns->pReg->szName), "ReqHandler");
3062 szSymbol[sizeof("devR0") - 1] = RT_C_TO_UPPER(szSymbol[sizeof("devR0") - 1]);
3063
3064 PFNPDMDRVREQHANDLERR0 pfnReqHandlerR0;
3065 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, szSymbol, &pfnReqHandlerR0);
3066 if (RT_SUCCESS(rc))
3067 {
3068 /*
3069 * Make the ring-0 call.
3070 */
3071 PDMDEVICECALLREQHANDLERREQ Req;
3072 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
3073 Req.Hdr.cbReq = sizeof(Req);
3074 Req.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3075 Req.pfnReqHandlerR0 = pfnReqHandlerR0;
3076 Req.uOperation = uOperation;
3077 Req.u32Alignment = 0;
3078 Req.u64Arg = u64Arg;
3079 rc = SUPR3CallVMMR0Ex(VMCC_GET_VMR0_FOR_CALL(pVM), NIL_VMCPUID, VMMR0_DO_PDM_DEVICE_CALL_REQ_HANDLER, 0, &Req.Hdr);
3080 }
3081 else
3082 pfnReqHandlerR0 = NIL_RTR0PTR;
3083 }
3084 else
3085 rc = VERR_ACCESS_DENIED;
3086 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3087 pDevIns->iInstance, rc));
3088 return rc;
3089}
3090
3091
3092/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetSuspendReason} */
3093static DECLCALLBACK(VMSUSPENDREASON) pdmR3DevHlp_VMGetSuspendReason(PPDMDEVINS pDevIns)
3094{
3095 PDMDEV_ASSERT_DEVINS(pDevIns);
3096 PVM pVM = pDevIns->Internal.s.pVMR3;
3097 VM_ASSERT_EMT(pVM);
3098 VMSUSPENDREASON enmReason = VMR3GetSuspendReason(pVM->pUVM);
3099 LogFlow(("pdmR3DevHlp_VMGetSuspendReason: caller='%s'/%d: returns %d\n",
3100 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3101 return enmReason;
3102}
3103
3104
3105/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetResumeReason} */
3106static DECLCALLBACK(VMRESUMEREASON) pdmR3DevHlp_VMGetResumeReason(PPDMDEVINS pDevIns)
3107{
3108 PDMDEV_ASSERT_DEVINS(pDevIns);
3109 PVM pVM = pDevIns->Internal.s.pVMR3;
3110 VM_ASSERT_EMT(pVM);
3111 VMRESUMEREASON enmReason = VMR3GetResumeReason(pVM->pUVM);
3112 LogFlow(("pdmR3DevHlp_VMGetResumeReason: caller='%s'/%d: returns %d\n",
3113 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3114 return enmReason;
3115}
3116
3117
3118/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
3119static DECLCALLBACK(PUVM) pdmR3DevHlp_GetUVM(PPDMDEVINS pDevIns)
3120{
3121 PDMDEV_ASSERT_DEVINS(pDevIns);
3122 LogFlow(("pdmR3DevHlp_GetUVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3123 return pDevIns->Internal.s.pVMR3->pUVM;
3124}
3125
3126
3127/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
3128static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
3129{
3130 PDMDEV_ASSERT_DEVINS(pDevIns);
3131 LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3132 return pDevIns->Internal.s.pVMR3;
3133}
3134
3135
3136/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
3137static DECLCALLBACK(PVMCPU) pdmR3DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
3138{
3139 PDMDEV_ASSERT_DEVINS(pDevIns);
3140 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3141 LogFlow(("pdmR3DevHlp_GetVMCPU: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, VMMGetCpuId(pDevIns->Internal.s.pVMR3)));
3142 return VMMGetCpu(pDevIns->Internal.s.pVMR3);
3143}
3144
3145
3146/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
3147static DECLCALLBACK(VMCPUID) pdmR3DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
3148{
3149 PDMDEV_ASSERT_DEVINS(pDevIns);
3150 VMCPUID idCpu = VMMGetCpuId(pDevIns->Internal.s.pVMR3);
3151 LogFlow(("pdmR3DevHlp_GetCurrentCpuId: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, idCpu));
3152 return idCpu;
3153}
3154
3155
3156/** @interface_method_impl{PDMDEVHLPR3,pfnPCIBusRegister} */
3157static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREGR3 pPciBusReg,
3158 PCPDMPCIHLPR3 *ppPciHlp, uint32_t *piBus)
3159{
3160 PDMDEV_ASSERT_DEVINS(pDevIns);
3161 PVM pVM = pDevIns->Internal.s.pVMR3;
3162 VM_ASSERT_EMT(pVM);
3163 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, "
3164 ".pfnInterceptConfigAccesses=%p, pfnConfigRead=%p, pfnConfigWrite=%p, .pfnSetIrqR3=%p, .u32EndVersion=%#x} ppPciHlpR3=%p piBus=%p\n",
3165 pDevIns->pReg->szName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
3166 pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnInterceptConfigAccesses, pPciBusReg->pfnConfigRead,
3167 pPciBusReg->pfnConfigWrite, pPciBusReg->pfnSetIrqR3, pPciBusReg->u32EndVersion, ppPciHlp, piBus));
3168
3169 /*
3170 * Validate the structure and output parameters.
3171 */
3172 AssertLogRelMsgReturn(pPciBusReg->u32Version == PDM_PCIBUSREGR3_VERSION,
3173 ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
3174 VERR_INVALID_PARAMETER);
3175 AssertPtrReturn(pPciBusReg->pfnRegisterR3, VERR_INVALID_PARAMETER);
3176 AssertPtrNullReturn(pPciBusReg->pfnRegisterMsiR3, VERR_INVALID_POINTER);
3177 AssertPtrReturn(pPciBusReg->pfnIORegionRegisterR3, VERR_INVALID_POINTER);
3178 AssertPtrReturn(pPciBusReg->pfnInterceptConfigAccesses, VERR_INVALID_POINTER);
3179 AssertPtrReturn(pPciBusReg->pfnConfigWrite, VERR_INVALID_POINTER);
3180 AssertPtrReturn(pPciBusReg->pfnConfigRead, VERR_INVALID_POINTER);
3181 AssertPtrReturn(pPciBusReg->pfnSetIrqR3, VERR_INVALID_POINTER);
3182 AssertLogRelMsgReturn(pPciBusReg->u32EndVersion == PDM_PCIBUSREGR3_VERSION,
3183 ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
3184 VERR_INVALID_PARAMETER);
3185 AssertPtrReturn(ppPciHlp, VERR_INVALID_POINTER);
3186 AssertPtrNullReturn(piBus, VERR_INVALID_POINTER);
3187 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3188
3189 /*
3190 * Find free PCI bus entry.
3191 */
3192 unsigned iBus = 0;
3193 for (iBus = 0; iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
3194 if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
3195 break;
3196 AssertLogRelMsgReturn(iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses),
3197 ("Too many PCI buses. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aPciBuses)),
3198 VERR_OUT_OF_RESOURCES);
3199 PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
3200
3201 /*
3202 * Init the R3 bits.
3203 */
3204 pPciBus->iBus = iBus;
3205 pPciBus->pDevInsR3 = pDevIns;
3206 pPciBus->pfnRegister = pPciBusReg->pfnRegisterR3;
3207 pPciBus->pfnRegisterMsi = pPciBusReg->pfnRegisterMsiR3;
3208 pPciBus->pfnIORegionRegister = pPciBusReg->pfnIORegionRegisterR3;
3209 pPciBus->pfnInterceptConfigAccesses = pPciBusReg->pfnInterceptConfigAccesses;
3210 pPciBus->pfnConfigRead = pPciBusReg->pfnConfigRead;
3211 pPciBus->pfnConfigWrite = pPciBusReg->pfnConfigWrite;
3212 pPciBus->pfnSetIrqR3 = pPciBusReg->pfnSetIrqR3;
3213
3214 Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3215
3216 /* set the helper pointer and return. */
3217 *ppPciHlp = &g_pdmR3DevPciHlp;
3218 if (piBus)
3219 *piBus = iBus;
3220 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc *piBus=%u\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS, iBus));
3221 return VINF_SUCCESS;
3222}
3223
3224
3225/** @interface_method_impl{PDMDEVHLPR3,pfnPICRegister} */
3226static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
3227{
3228 PDMDEV_ASSERT_DEVINS(pDevIns);
3229 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3230 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",
3231 pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrqR3, pPicReg->pfnGetInterruptR3,
3232 pPicReg->pszSetIrqRC, pPicReg->pszSetIrqRC, pPicReg->pszGetInterruptRC, pPicReg->pszGetInterruptRC,
3233 pPicReg->pszSetIrqR0, pPicReg->pszSetIrqR0, pPicReg->pszGetInterruptR0, pPicReg->pszGetInterruptR0,
3234 ppPicHlpR3));
3235
3236 /*
3237 * Validate input.
3238 */
3239 if (pPicReg->u32Version != PDM_PICREG_VERSION)
3240 {
3241 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPicReg->u32Version, PDM_PICREG_VERSION));
3242 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3243 return VERR_INVALID_PARAMETER;
3244 }
3245 if ( !pPicReg->pfnSetIrqR3
3246 || !pPicReg->pfnGetInterruptR3)
3247 {
3248 Assert(pPicReg->pfnSetIrqR3);
3249 Assert(pPicReg->pfnGetInterruptR3);
3250 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (R3 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3251 return VERR_INVALID_PARAMETER;
3252 }
3253 if ( ( pPicReg->pszSetIrqRC
3254 || pPicReg->pszGetInterruptRC)
3255 && ( !VALID_PTR(pPicReg->pszSetIrqRC)
3256 || !VALID_PTR(pPicReg->pszGetInterruptRC))
3257 )
3258 {
3259 Assert(VALID_PTR(pPicReg->pszSetIrqRC));
3260 Assert(VALID_PTR(pPicReg->pszGetInterruptRC));
3261 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (RC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3262 return VERR_INVALID_PARAMETER;
3263 }
3264 if ( pPicReg->pszSetIrqRC
3265 && !(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC))
3266 {
3267 Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC);
3268 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (RC flag)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3269 return VERR_INVALID_PARAMETER;
3270 }
3271 if ( pPicReg->pszSetIrqR0
3272 && !(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0))
3273 {
3274 Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0);
3275 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (R0 flag)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3276 return VERR_INVALID_PARAMETER;
3277 }
3278 if (!ppPicHlpR3)
3279 {
3280 Assert(ppPicHlpR3);
3281 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (ppPicHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3282 return VERR_INVALID_PARAMETER;
3283 }
3284
3285 /*
3286 * Only one PIC device.
3287 */
3288 PVM pVM = pDevIns->Internal.s.pVMR3;
3289 if (pVM->pdm.s.Pic.pDevInsR3)
3290 {
3291 AssertMsgFailed(("Only one pic device is supported!\n"));
3292 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3293 return VERR_INVALID_PARAMETER;
3294 }
3295
3296 /*
3297 * RC stuff.
3298 */
3299 if (pPicReg->pszSetIrqRC)
3300 {
3301 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pPicReg->pszSetIrqRC, &pVM->pdm.s.Pic.pfnSetIrqRC);
3302 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pPicReg->pszSetIrqRC, rc));
3303 if (RT_SUCCESS(rc))
3304 {
3305 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pPicReg->pszGetInterruptRC, &pVM->pdm.s.Pic.pfnGetInterruptRC);
3306 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pPicReg->pszGetInterruptRC, rc));
3307 }
3308 if (RT_FAILURE(rc))
3309 {
3310 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3311 return rc;
3312 }
3313 pVM->pdm.s.Pic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3314 }
3315 else
3316 {
3317 pVM->pdm.s.Pic.pDevInsRC = 0;
3318 pVM->pdm.s.Pic.pfnSetIrqRC = 0;
3319 pVM->pdm.s.Pic.pfnGetInterruptRC = 0;
3320 }
3321
3322 /*
3323 * R0 stuff.
3324 */
3325 if (pPicReg->pszSetIrqR0)
3326 {
3327 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pPicReg->pszSetIrqR0, &pVM->pdm.s.Pic.pfnSetIrqR0);
3328 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pPicReg->pszSetIrqR0, rc));
3329 if (RT_SUCCESS(rc))
3330 {
3331 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pPicReg->pszGetInterruptR0, &pVM->pdm.s.Pic.pfnGetInterruptR0);
3332 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pPicReg->pszGetInterruptR0, rc));
3333 }
3334 if (RT_FAILURE(rc))
3335 {
3336 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3337 return rc;
3338 }
3339 pVM->pdm.s.Pic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3340 Assert(pVM->pdm.s.Pic.pDevInsR0);
3341 }
3342 else
3343 {
3344 pVM->pdm.s.Pic.pfnSetIrqR0 = 0;
3345 pVM->pdm.s.Pic.pfnGetInterruptR0 = 0;
3346 pVM->pdm.s.Pic.pDevInsR0 = 0;
3347 }
3348
3349 /*
3350 * R3 stuff.
3351 */
3352 pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
3353 pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrqR3;
3354 pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterruptR3;
3355 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3356
3357 /* set the helper pointer and return. */
3358 *ppPicHlpR3 = &g_pdmR3DevPicHlp;
3359 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3360 return VINF_SUCCESS;
3361}
3362
3363
3364/** @interface_method_impl{PDMDEVHLPR3,pfnAPICRegister} */
3365static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns)
3366{
3367 PDMDEV_ASSERT_DEVINS(pDevIns);
3368 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3369
3370 /*
3371 * Only one APIC device. On SMP we have single logical device covering all LAPICs,
3372 * as they need to communicate and share state easily.
3373 */
3374 PVM pVM = pDevIns->Internal.s.pVMR3;
3375 if (pVM->pdm.s.Apic.pDevInsR3)
3376 {
3377 AssertMsgFailed(("Only one APIC device is supported!\n"));
3378 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3379 return VERR_INVALID_PARAMETER;
3380 }
3381
3382 /*
3383 * Initialize the RC, R0 and HC bits.
3384 */
3385 pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3386 Assert(pVM->pdm.s.Apic.pDevInsRC || !VM_IS_RAW_MODE_ENABLED(pVM));
3387
3388 pVM->pdm.s.Apic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3389 Assert(pVM->pdm.s.Apic.pDevInsR0);
3390
3391 pVM->pdm.s.Apic.pDevInsR3 = pDevIns;
3392 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3393 return VINF_SUCCESS;
3394}
3395
3396
3397/** @interface_method_impl{PDMDEVHLPR3,pfnIOAPICRegister} */
3398static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
3399{
3400 PDMDEV_ASSERT_DEVINS(pDevIns);
3401 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3402 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppIoApicHlpR3=%p\n",
3403 pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqR3,
3404 pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqR0, pIoApicReg->pszSetIrqR0, ppIoApicHlpR3));
3405
3406 /*
3407 * Validate input.
3408 */
3409 if (pIoApicReg->u32Version != PDM_IOAPICREG_VERSION)
3410 {
3411 AssertMsgFailed(("u32Version=%#x expected %#x\n", pIoApicReg->u32Version, PDM_IOAPICREG_VERSION));
3412 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3413 return VERR_INVALID_PARAMETER;
3414 }
3415 if (!pIoApicReg->pfnSetIrqR3 || !pIoApicReg->pfnSendMsiR3 || !pIoApicReg->pfnSetEoiR3)
3416 {
3417 Assert(pIoApicReg->pfnSetIrqR3);
3418 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (R3 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3419 return VERR_INVALID_PARAMETER;
3420 }
3421 if ( pIoApicReg->pszSetIrqRC
3422 && !VALID_PTR(pIoApicReg->pszSetIrqRC))
3423 {
3424 Assert(VALID_PTR(pIoApicReg->pszSetIrqRC));
3425 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3426 return VERR_INVALID_PARAMETER;
3427 }
3428 if ( pIoApicReg->pszSendMsiRC
3429 && !VALID_PTR(pIoApicReg->pszSendMsiRC))
3430 {
3431 Assert(VALID_PTR(pIoApicReg->pszSendMsiRC));
3432 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3433 return VERR_INVALID_PARAMETER;
3434 }
3435 if ( pIoApicReg->pszSetEoiRC
3436 && !VALID_PTR(pIoApicReg->pszSetEoiRC))
3437 {
3438 Assert(VALID_PTR(pIoApicReg->pszSetEoiRC));
3439 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3440 return VERR_INVALID_PARAMETER;
3441 }
3442 if ( pIoApicReg->pszSetIrqR0
3443 && !VALID_PTR(pIoApicReg->pszSetIrqR0))
3444 {
3445 Assert(VALID_PTR(pIoApicReg->pszSetIrqR0));
3446 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3447 return VERR_INVALID_PARAMETER;
3448 }
3449 if ( pIoApicReg->pszSendMsiR0
3450 && !VALID_PTR(pIoApicReg->pszSendMsiR0))
3451 {
3452 Assert(VALID_PTR(pIoApicReg->pszSendMsiR0));
3453 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3454 return VERR_INVALID_PARAMETER;
3455 }
3456 if ( pIoApicReg->pszSetEoiR0
3457 && !VALID_PTR(pIoApicReg->pszSetEoiR0))
3458 {
3459 Assert(VALID_PTR(pIoApicReg->pszSetEoiR0));
3460 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3461 return VERR_INVALID_PARAMETER;
3462 }
3463 if (!ppIoApicHlpR3)
3464 {
3465 Assert(ppIoApicHlpR3);
3466 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (ppApicHlp)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3467 return VERR_INVALID_PARAMETER;
3468 }
3469
3470 /*
3471 * The I/O APIC requires the APIC to be present (hacks++).
3472 * If the I/O APIC does GC stuff so must the APIC.
3473 */
3474 PVM pVM = pDevIns->Internal.s.pVMR3;
3475 if (!pVM->pdm.s.Apic.pDevInsR3)
3476 {
3477 AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
3478 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (no APIC)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3479 return VERR_INVALID_PARAMETER;
3480 }
3481#if 0
3482 if ( pIoApicReg->pszSetIrqRC
3483 && !pVM->pdm.s.Apic.pDevInsRC)
3484 {
3485 AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
3486 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (no GC APIC)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3487 return VERR_INVALID_PARAMETER;
3488 }
3489#endif
3490
3491 /*
3492 * Only one I/O APIC device.
3493 */
3494 if (pVM->pdm.s.IoApic.pDevInsR3)
3495 {
3496 AssertMsgFailed(("Only one ioapic device is supported!\n"));
3497 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (only one)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3498 return VERR_INVALID_PARAMETER;
3499 }
3500
3501 /*
3502 * Resolve & initialize the GC bits.
3503 */
3504 if (pIoApicReg->pszSetIrqRC)
3505 {
3506 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSetIrqRC, &pVM->pdm.s.IoApic.pfnSetIrqRC);
3507 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pIoApicReg->pszSetIrqRC, rc));
3508 if (RT_FAILURE(rc))
3509 {
3510 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3511 return rc;
3512 }
3513 pVM->pdm.s.IoApic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3514 }
3515 else
3516 {
3517 pVM->pdm.s.IoApic.pDevInsRC = 0;
3518 pVM->pdm.s.IoApic.pfnSetIrqRC = 0;
3519 }
3520
3521 if (pIoApicReg->pszSendMsiRC)
3522 {
3523 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSendMsiRC, &pVM->pdm.s.IoApic.pfnSendMsiRC);
3524 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pIoApicReg->pszSendMsiRC, rc));
3525 if (RT_FAILURE(rc))
3526 {
3527 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3528 return rc;
3529 }
3530 }
3531 else
3532 {
3533 pVM->pdm.s.IoApic.pfnSendMsiRC = 0;
3534 }
3535
3536 if (pIoApicReg->pszSetEoiRC)
3537 {
3538 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSetEoiRC, &pVM->pdm.s.IoApic.pfnSetEoiRC);
3539 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pIoApicReg->pszSetEoiRC, rc));
3540 if (RT_FAILURE(rc))
3541 {
3542 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3543 return rc;
3544 }
3545 }
3546 else
3547 {
3548 pVM->pdm.s.IoApic.pfnSetEoiRC = 0;
3549 }
3550
3551 /*
3552 * Resolve & initialize the R0 bits.
3553 */
3554 if (pIoApicReg->pszSetIrqR0)
3555 {
3556 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSetIrqR0);
3557 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pIoApicReg->pszSetIrqR0, rc));
3558 if (RT_FAILURE(rc))
3559 {
3560 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3561 return rc;
3562 }
3563 pVM->pdm.s.IoApic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3564 Assert(pVM->pdm.s.IoApic.pDevInsR0);
3565 }
3566 else
3567 {
3568 pVM->pdm.s.IoApic.pfnSetIrqR0 = 0;
3569 pVM->pdm.s.IoApic.pDevInsR0 = 0;
3570 }
3571
3572 if (pIoApicReg->pszSendMsiR0)
3573 {
3574 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSendMsiR0, &pVM->pdm.s.IoApic.pfnSendMsiR0);
3575 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pIoApicReg->pszSendMsiR0, rc));
3576 if (RT_FAILURE(rc))
3577 {
3578 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3579 return rc;
3580 }
3581 }
3582 else
3583 {
3584 pVM->pdm.s.IoApic.pfnSendMsiR0 = 0;
3585 }
3586
3587 if (pIoApicReg->pszSetEoiR0)
3588 {
3589 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSetEoiR0, &pVM->pdm.s.IoApic.pfnSetEoiR0);
3590 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pIoApicReg->pszSetEoiR0, rc));
3591 if (RT_FAILURE(rc))
3592 {
3593 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3594 return rc;
3595 }
3596 }
3597 else
3598 {
3599 pVM->pdm.s.IoApic.pfnSetEoiR0 = 0;
3600 }
3601
3602
3603 /*
3604 * Initialize the R3 bits.
3605 */
3606 pVM->pdm.s.IoApic.pDevInsR3 = pDevIns;
3607 pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrqR3;
3608 pVM->pdm.s.IoApic.pfnSendMsiR3 = pIoApicReg->pfnSendMsiR3;
3609 pVM->pdm.s.IoApic.pfnSetEoiR3 = pIoApicReg->pfnSetEoiR3;
3610 Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3611
3612 /* set the helper pointer and return. */
3613 *ppIoApicHlpR3 = &g_pdmR3DevIoApicHlp;
3614 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3615 return VINF_SUCCESS;
3616}
3617
3618
3619/** @interface_method_impl{PDMDEVHLPR3,pfnHPETRegister} */
3620static DECLCALLBACK(int) pdmR3DevHlp_HPETRegister(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3)
3621{
3622 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
3623 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3624 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3625
3626 /*
3627 * Validate input.
3628 */
3629 if (pHpetReg->u32Version != PDM_HPETREG_VERSION)
3630 {
3631 AssertMsgFailed(("u32Version=%#x expected %#x\n", pHpetReg->u32Version, PDM_HPETREG_VERSION));
3632 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3633 return VERR_INVALID_PARAMETER;
3634 }
3635
3636 if (!ppHpetHlpR3)
3637 {
3638 Assert(ppHpetHlpR3);
3639 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d: returns %Rrc (ppApicHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3640 return VERR_INVALID_PARAMETER;
3641 }
3642
3643 /* set the helper pointer and return. */
3644 *ppHpetHlpR3 = &g_pdmR3DevHpetHlp;
3645 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3646 return VINF_SUCCESS;
3647}
3648
3649
3650/** @interface_method_impl{PDMDEVHLPR3,pfnPciRawRegister} */
3651static DECLCALLBACK(int) pdmR3DevHlp_PciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
3652{
3653 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
3654 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3655 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3656
3657 /*
3658 * Validate input.
3659 */
3660 if (pPciRawReg->u32Version != PDM_PCIRAWREG_VERSION)
3661 {
3662 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciRawReg->u32Version, PDM_PCIRAWREG_VERSION));
3663 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3664 return VERR_INVALID_PARAMETER;
3665 }
3666
3667 if (!ppPciRawHlpR3)
3668 {
3669 Assert(ppPciRawHlpR3);
3670 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (ppPciRawHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3671 return VERR_INVALID_PARAMETER;
3672 }
3673
3674 /* set the helper pointer and return. */
3675 *ppPciRawHlpR3 = &g_pdmR3DevPciRawHlp;
3676 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3677 return VINF_SUCCESS;
3678}
3679
3680
3681/** @interface_method_impl{PDMDEVHLPR3,pfnDMACRegister} */
3682static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
3683{
3684 PDMDEV_ASSERT_DEVINS(pDevIns);
3685 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3686 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",
3687 pDevIns->pReg->szName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
3688 pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
3689
3690 /*
3691 * Validate input.
3692 */
3693 if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
3694 {
3695 AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
3696 PDM_DMACREG_VERSION));
3697 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (version)\n",
3698 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3699 return VERR_INVALID_PARAMETER;
3700 }
3701 if ( !pDmacReg->pfnRun
3702 || !pDmacReg->pfnRegister
3703 || !pDmacReg->pfnReadMemory
3704 || !pDmacReg->pfnWriteMemory
3705 || !pDmacReg->pfnSetDREQ
3706 || !pDmacReg->pfnGetChannelMode)
3707 {
3708 Assert(pDmacReg->pfnRun);
3709 Assert(pDmacReg->pfnRegister);
3710 Assert(pDmacReg->pfnReadMemory);
3711 Assert(pDmacReg->pfnWriteMemory);
3712 Assert(pDmacReg->pfnSetDREQ);
3713 Assert(pDmacReg->pfnGetChannelMode);
3714 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3715 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3716 return VERR_INVALID_PARAMETER;
3717 }
3718
3719 if (!ppDmacHlp)
3720 {
3721 Assert(ppDmacHlp);
3722 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (ppDmacHlp)\n",
3723 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3724 return VERR_INVALID_PARAMETER;
3725 }
3726
3727 /*
3728 * Only one DMA device.
3729 */
3730 PVM pVM = pDevIns->Internal.s.pVMR3;
3731 if (pVM->pdm.s.pDmac)
3732 {
3733 AssertMsgFailed(("Only one DMA device is supported!\n"));
3734 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3735 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3736 return VERR_INVALID_PARAMETER;
3737 }
3738
3739 /*
3740 * Allocate and initialize pci bus structure.
3741 */
3742 int rc = VINF_SUCCESS;
3743 PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
3744 if (pDmac)
3745 {
3746 pDmac->pDevIns = pDevIns;
3747 pDmac->Reg = *pDmacReg;
3748 pVM->pdm.s.pDmac = pDmac;
3749
3750 /* set the helper pointer. */
3751 *ppDmacHlp = &g_pdmR3DevDmacHlp;
3752 Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
3753 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3754 }
3755 else
3756 rc = VERR_NO_MEMORY;
3757
3758 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3759 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3760 return rc;
3761}
3762
3763
3764/**
3765 * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
3766 */
3767static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbHeap)
3768{
3769 PDMDEV_ASSERT_DEVINS(pDevIns);
3770 PVM pVM = pDevIns->Internal.s.pVMR3;
3771 VM_ASSERT_EMT(pVM);
3772 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: GCPhys=%RGp pvHeap=%p cbHeap=%#x\n",
3773 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvHeap, cbHeap));
3774
3775 if (pVM->pdm.s.pvVMMDevHeap == NULL)
3776 {
3777 pVM->pdm.s.pvVMMDevHeap = pvHeap;
3778 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
3779 pVM->pdm.s.cbVMMDevHeap = cbHeap;
3780 pVM->pdm.s.cbVMMDevHeapLeft = cbHeap;
3781 }
3782 else
3783 {
3784 Assert(pVM->pdm.s.pvVMMDevHeap == pvHeap);
3785 Assert(pVM->pdm.s.cbVMMDevHeap == cbHeap);
3786 Assert(pVM->pdm.s.GCPhysVMMDevHeap != GCPhys || GCPhys == NIL_RTGCPHYS);
3787 if (pVM->pdm.s.GCPhysVMMDevHeap != GCPhys)
3788 {
3789 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
3790 if (pVM->pdm.s.pfnVMMDevHeapNotify)
3791 pVM->pdm.s.pfnVMMDevHeapNotify(pVM, pvHeap, GCPhys);
3792 }
3793 }
3794
3795 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: returns %Rrc\n",
3796 pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3797 return VINF_SUCCESS;
3798}
3799
3800
3801/**
3802 * @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister}
3803 */
3804static DECLCALLBACK(int) pdmR3DevHlp_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
3805{
3806 PDMDEV_ASSERT_DEVINS(pDevIns);
3807 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3808 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: pFWReg=%p:{.u32Version=%#x, .pfnIsHardReset=%p, .u32TheEnd=%#x} ppFwHlp=%p\n",
3809 pDevIns->pReg->szName, pDevIns->iInstance, pFwReg, pFwReg->u32Version, pFwReg->pfnIsHardReset, pFwReg->u32TheEnd, ppFwHlp));
3810
3811 /*
3812 * Validate input.
3813 */
3814 if (pFwReg->u32Version != PDM_FWREG_VERSION)
3815 {
3816 AssertMsgFailed(("u32Version=%#x expected %#x\n", pFwReg->u32Version, PDM_FWREG_VERSION));
3817 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (version)\n",
3818 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3819 return VERR_INVALID_PARAMETER;
3820 }
3821 if (!pFwReg->pfnIsHardReset)
3822 {
3823 Assert(pFwReg->pfnIsHardReset);
3824 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3825 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3826 return VERR_INVALID_PARAMETER;
3827 }
3828
3829 if (!ppFwHlp)
3830 {
3831 Assert(ppFwHlp);
3832 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (ppFwHlp)\n",
3833 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3834 return VERR_INVALID_PARAMETER;
3835 }
3836
3837 /*
3838 * Only one DMA device.
3839 */
3840 PVM pVM = pDevIns->Internal.s.pVMR3;
3841 if (pVM->pdm.s.pFirmware)
3842 {
3843 AssertMsgFailed(("Only one firmware device is supported!\n"));
3844 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
3845 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3846 return VERR_INVALID_PARAMETER;
3847 }
3848
3849 /*
3850 * Allocate and initialize pci bus structure.
3851 */
3852 int rc = VINF_SUCCESS;
3853 PPDMFW pFirmware = (PPDMFW)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pFirmware));
3854 if (pFirmware)
3855 {
3856 pFirmware->pDevIns = pDevIns;
3857 pFirmware->Reg = *pFwReg;
3858 pVM->pdm.s.pFirmware = pFirmware;
3859
3860 /* set the helper pointer. */
3861 *ppFwHlp = &g_pdmR3DevFirmwareHlp;
3862 Log(("PDM: Registered firmware device '%s'/%d pDevIns=%p\n",
3863 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3864 }
3865 else
3866 rc = VERR_NO_MEMORY;
3867
3868 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
3869 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3870 return rc;
3871}
3872
3873
3874/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
3875static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
3876{
3877 PDMDEV_ASSERT_DEVINS(pDevIns);
3878 PVM pVM = pDevIns->Internal.s.pVMR3;
3879 VM_ASSERT_EMT(pVM);
3880 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: fFlags=%#x VM_FF_RESET %d -> 1\n",
3881 pDevIns->pReg->szName, pDevIns->iInstance, fFlags, VM_FF_IS_SET(pVM, VM_FF_RESET)));
3882
3883 /*
3884 * We postpone this operation because we're likely to be inside a I/O instruction
3885 * and the EIP will be updated when we return.
3886 * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
3887 */
3888 bool fHaltOnReset;
3889 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
3890 if (RT_SUCCESS(rc) && fHaltOnReset)
3891 {
3892 Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
3893 rc = VINF_EM_HALT;
3894 }
3895 else
3896 {
3897 pVM->pdm.s.fResetFlags = fFlags;
3898 VM_FF_SET(pVM, VM_FF_RESET);
3899 rc = VINF_EM_RESET;
3900 }
3901
3902 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3903 return rc;
3904}
3905
3906
3907/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
3908static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
3909{
3910 int rc;
3911 PDMDEV_ASSERT_DEVINS(pDevIns);
3912 PVM pVM = pDevIns->Internal.s.pVMR3;
3913 VM_ASSERT_EMT(pVM);
3914 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
3915 pDevIns->pReg->szName, pDevIns->iInstance));
3916
3917 /** @todo Always take the SMP path - fewer code paths. */
3918 if (pVM->cCpus > 1)
3919 {
3920 /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
3921 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3Suspend, 2, pVM->pUVM, VMSUSPENDREASON_VM);
3922 AssertRC(rc);
3923 rc = VINF_EM_SUSPEND;
3924 }
3925 else
3926 rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
3927
3928 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3929 return rc;
3930}
3931
3932
3933/**
3934 * Worker for pdmR3DevHlp_VMSuspendSaveAndPowerOff that is invoked via a queued
3935 * EMT request to avoid deadlocks.
3936 *
3937 * @returns VBox status code fit for scheduling.
3938 * @param pVM The cross context VM structure.
3939 * @param pDevIns The device that triggered this action.
3940 */
3941static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker(PVM pVM, PPDMDEVINS pDevIns)
3942{
3943 /*
3944 * Suspend the VM first then do the saving.
3945 */
3946 int rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
3947 if (RT_SUCCESS(rc))
3948 {
3949 PUVM pUVM = pVM->pUVM;
3950 rc = pUVM->pVmm2UserMethods->pfnSaveState(pVM->pUVM->pVmm2UserMethods, pUVM);
3951
3952 /*
3953 * On success, power off the VM, on failure we'll leave it suspended.
3954 */
3955 if (RT_SUCCESS(rc))
3956 {
3957 rc = VMR3PowerOff(pVM->pUVM);
3958 if (RT_FAILURE(rc))
3959 LogRel(("%s/SSP: VMR3PowerOff failed: %Rrc\n", pDevIns->pReg->szName, rc));
3960 }
3961 else
3962 LogRel(("%s/SSP: pfnSaveState failed: %Rrc\n", pDevIns->pReg->szName, rc));
3963 }
3964 else
3965 LogRel(("%s/SSP: Suspend failed: %Rrc\n", pDevIns->pReg->szName, rc));
3966 return rc;
3967}
3968
3969
3970/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
3971static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
3972{
3973 PDMDEV_ASSERT_DEVINS(pDevIns);
3974 PVM pVM = pDevIns->Internal.s.pVMR3;
3975 VM_ASSERT_EMT(pVM);
3976 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d:\n",
3977 pDevIns->pReg->szName, pDevIns->iInstance));
3978
3979 int rc;
3980 if ( pVM->pUVM->pVmm2UserMethods
3981 && pVM->pUVM->pVmm2UserMethods->pfnSaveState)
3982 {
3983 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker, 2, pVM, pDevIns);
3984 if (RT_SUCCESS(rc))
3985 {
3986 LogRel(("%s: Suspending, Saving and Powering Off the VM\n", pDevIns->pReg->szName));
3987 rc = VINF_EM_SUSPEND;
3988 }
3989 }
3990 else
3991 rc = VERR_NOT_SUPPORTED;
3992
3993 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3994 return rc;
3995}
3996
3997
3998/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
3999static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
4000{
4001 int rc;
4002 PDMDEV_ASSERT_DEVINS(pDevIns);
4003 PVM pVM = pDevIns->Internal.s.pVMR3;
4004 VM_ASSERT_EMT(pVM);
4005 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
4006 pDevIns->pReg->szName, pDevIns->iInstance));
4007
4008 /** @todo Always take the SMP path - fewer code paths. */
4009 if (pVM->cCpus > 1)
4010 {
4011 /* We might be holding locks here and could cause a deadlock since
4012 VMR3PowerOff rendezvous with the other CPUs. */
4013 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3PowerOff, 1, pVM->pUVM);
4014 AssertRC(rc);
4015 /* Set the VCPU state to stopped here as well to make sure no
4016 inconsistency with the EM state occurs. */
4017 VMCPU_SET_STATE(VMMGetCpu(pVM), VMCPUSTATE_STOPPED);
4018 rc = VINF_EM_OFF;
4019 }
4020 else
4021 rc = VMR3PowerOff(pVM->pUVM);
4022
4023 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4024 return rc;
4025}
4026
4027
4028/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
4029static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
4030{
4031 PDMDEV_ASSERT_DEVINS(pDevIns);
4032 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4033
4034 bool fRc = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pVMR3));
4035
4036 LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pReg->szName, pDevIns->iInstance, fRc));
4037 return fRc;
4038}
4039
4040
4041/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
4042static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
4043{
4044 PDMDEV_ASSERT_DEVINS(pDevIns);
4045 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4046 LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, fEnable));
4047 PGMR3PhysSetA20(VMMGetCpu(pDevIns->Internal.s.pVMR3), fEnable);
4048}
4049
4050
4051/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
4052static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
4053 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
4054{
4055 PDMDEV_ASSERT_DEVINS(pDevIns);
4056 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4057
4058 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
4059 pDevIns->pReg->szName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
4060 AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
4061
4062 CPUMGetGuestCpuId(VMMGetCpu(pDevIns->Internal.s.pVMR3), iLeaf, 0 /*iSubLeaf*/, pEax, pEbx, pEcx, pEdx);
4063
4064 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
4065 pDevIns->pReg->szName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
4066}
4067
4068
4069/**
4070 * The device helper structure for trusted devices.
4071 */
4072const PDMDEVHLPR3 g_pdmR3DevHlpTrusted =
4073{
4074 PDM_DEVHLPR3_VERSION,
4075 pdmR3DevHlp_IoPortCreateEx,
4076 pdmR3DevHlp_IoPortMap,
4077 pdmR3DevHlp_IoPortUnmap,
4078 pdmR3DevHlp_IOPortRegister,
4079 pdmR3DevHlp_IOPortRegisterRC,
4080 pdmR3DevHlp_IOPortRegisterR0,
4081 pdmR3DevHlp_IOPortDeregister,
4082 pdmR3DevHlp_MmioCreateEx,
4083 pdmR3DevHlp_MmioMap,
4084 pdmR3DevHlp_MmioUnmap,
4085 pdmR3DevHlp_MmioReduce,
4086 pdmR3DevHlp_MMIORegister,
4087 pdmR3DevHlp_MMIORegisterRC,
4088 pdmR3DevHlp_MMIORegisterR0,
4089 pdmR3DevHlp_MMIODeregister,
4090 pdmR3DevHlp_MMIO2Register,
4091 pdmR3DevHlp_MMIOExPreRegister,
4092 pdmR3DevHlp_MMIOExDeregister,
4093 pdmR3DevHlp_MMIOExMap,
4094 pdmR3DevHlp_MMIOExUnmap,
4095 pdmR3DevHlp_MMIOExReduce,
4096 pdmR3DevHlp_MMHyperMapMMIO2,
4097 pdmR3DevHlp_MMIO2MapKernel,
4098 pdmR3DevHlp_ROMRegister,
4099 pdmR3DevHlp_ROMProtectShadow,
4100 pdmR3DevHlp_SSMRegister,
4101 SSMR3PutStruct,
4102 SSMR3PutStructEx,
4103 SSMR3PutBool,
4104 SSMR3PutU8,
4105 SSMR3PutS8,
4106 SSMR3PutU16,
4107 SSMR3PutS16,
4108 SSMR3PutU32,
4109 SSMR3PutS32,
4110 SSMR3PutU64,
4111 SSMR3PutS64,
4112 SSMR3PutU128,
4113 SSMR3PutS128,
4114 SSMR3PutUInt,
4115 SSMR3PutSInt,
4116 SSMR3PutGCUInt,
4117 SSMR3PutGCUIntReg,
4118 SSMR3PutGCPhys32,
4119 SSMR3PutGCPhys64,
4120 SSMR3PutGCPhys,
4121 SSMR3PutGCPtr,
4122 SSMR3PutGCUIntPtr,
4123 SSMR3PutRCPtr,
4124 SSMR3PutIOPort,
4125 SSMR3PutSel,
4126 SSMR3PutMem,
4127 SSMR3PutStrZ,
4128 SSMR3GetStruct,
4129 SSMR3GetStructEx,
4130 SSMR3GetBool,
4131 SSMR3GetU8,
4132 SSMR3GetS8,
4133 SSMR3GetU16,
4134 SSMR3GetS16,
4135 SSMR3GetU32,
4136 SSMR3GetS32,
4137 SSMR3GetU64,
4138 SSMR3GetS64,
4139 SSMR3GetU128,
4140 SSMR3GetS128,
4141 SSMR3GetUInt,
4142 SSMR3GetSInt,
4143 SSMR3GetGCUInt,
4144 SSMR3GetGCUIntReg,
4145 SSMR3GetGCPhys32,
4146 SSMR3GetGCPhys64,
4147 SSMR3GetGCPhys,
4148 SSMR3GetGCPtr,
4149 SSMR3GetGCUIntPtr,
4150 SSMR3GetRCPtr,
4151 SSMR3GetIOPort,
4152 SSMR3GetSel,
4153 SSMR3GetMem,
4154 SSMR3GetStrZ,
4155 SSMR3GetStrZEx,
4156 SSMR3Skip,
4157 SSMR3SkipToEndOfUnit,
4158 SSMR3SetLoadError,
4159 SSMR3SetLoadErrorV,
4160 SSMR3SetCfgError,
4161 SSMR3SetCfgErrorV,
4162 SSMR3HandleGetStatus,
4163 SSMR3HandleGetAfter,
4164 SSMR3HandleIsLiveSave,
4165 SSMR3HandleMaxDowntime,
4166 SSMR3HandleHostBits,
4167 SSMR3HandleRevision,
4168 SSMR3HandleVersion,
4169 pdmR3DevHlp_TMTimerCreate,
4170 pdmR3DevHlp_TimerCreate,
4171 pdmR3DevHlp_TimerToPtr,
4172 pdmR3DevHlp_TimerFromMicro,
4173 pdmR3DevHlp_TimerFromMilli,
4174 pdmR3DevHlp_TimerFromNano,
4175 pdmR3DevHlp_TimerGet,
4176 pdmR3DevHlp_TimerGetFreq,
4177 pdmR3DevHlp_TimerGetNano,
4178 pdmR3DevHlp_TimerIsActive,
4179 pdmR3DevHlp_TimerIsLockOwner,
4180 pdmR3DevHlp_TimerLock,
4181 pdmR3DevHlp_TimerSet,
4182 pdmR3DevHlp_TimerSetFrequencyHint,
4183 pdmR3DevHlp_TimerSetMicro,
4184 pdmR3DevHlp_TimerSetMillies,
4185 pdmR3DevHlp_TimerSetNano,
4186 pdmR3DevHlp_TimerSetRelative,
4187 pdmR3DevHlp_TimerStop,
4188 pdmR3DevHlp_TimerUnlock,
4189 pdmR3DevHlp_TimerSave,
4190 pdmR3DevHlp_TimerLoad,
4191 pdmR3DevHlp_TMUtcNow,
4192 CFGMR3Exists,
4193 CFGMR3QueryType,
4194 CFGMR3QuerySize,
4195 CFGMR3QueryInteger,
4196 CFGMR3QueryIntegerDef,
4197 CFGMR3QueryString,
4198 CFGMR3QueryStringDef,
4199 CFGMR3QueryBytes,
4200 CFGMR3QueryU64,
4201 CFGMR3QueryU64Def,
4202 CFGMR3QueryS64,
4203 CFGMR3QueryS64Def,
4204 CFGMR3QueryU32,
4205 CFGMR3QueryU32Def,
4206 CFGMR3QueryS32,
4207 CFGMR3QueryS32Def,
4208 CFGMR3QueryU16,
4209 CFGMR3QueryU16Def,
4210 CFGMR3QueryS16,
4211 CFGMR3QueryS16Def,
4212 CFGMR3QueryU8,
4213 CFGMR3QueryU8Def,
4214 CFGMR3QueryS8,
4215 CFGMR3QueryS8Def,
4216 CFGMR3QueryBool,
4217 CFGMR3QueryBoolDef,
4218 CFGMR3QueryPort,
4219 CFGMR3QueryPortDef,
4220 CFGMR3QueryUInt,
4221 CFGMR3QueryUIntDef,
4222 CFGMR3QuerySInt,
4223 CFGMR3QuerySIntDef,
4224 CFGMR3QueryPtr,
4225 CFGMR3QueryPtrDef,
4226 CFGMR3QueryGCPtr,
4227 CFGMR3QueryGCPtrDef,
4228 CFGMR3QueryGCPtrU,
4229 CFGMR3QueryGCPtrUDef,
4230 CFGMR3QueryGCPtrS,
4231 CFGMR3QueryGCPtrSDef,
4232 CFGMR3QueryStringAlloc,
4233 CFGMR3QueryStringAllocDef,
4234 CFGMR3GetParent,
4235 CFGMR3GetChild,
4236 CFGMR3GetChildF,
4237 CFGMR3GetChildFV,
4238 CFGMR3GetFirstChild,
4239 CFGMR3GetNextChild,
4240 CFGMR3GetName,
4241 CFGMR3GetNameLen,
4242 CFGMR3AreChildrenValid,
4243 CFGMR3GetFirstValue,
4244 CFGMR3GetNextValue,
4245 CFGMR3GetValueName,
4246 CFGMR3GetValueNameLen,
4247 CFGMR3GetValueType,
4248 CFGMR3AreValuesValid,
4249 CFGMR3ValidateConfig,
4250 pdmR3DevHlp_PhysRead,
4251 pdmR3DevHlp_PhysWrite,
4252 pdmR3DevHlp_PhysGCPhys2CCPtr,
4253 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4254 pdmR3DevHlp_PhysReleasePageMappingLock,
4255 pdmR3DevHlp_PhysReadGCVirt,
4256 pdmR3DevHlp_PhysWriteGCVirt,
4257 pdmR3DevHlp_PhysGCPtr2GCPhys,
4258 pdmR3DevHlp_MMHeapAlloc,
4259 pdmR3DevHlp_MMHeapAllocZ,
4260 pdmR3DevHlp_MMHeapFree,
4261 pdmR3DevHlp_VMState,
4262 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4263 pdmR3DevHlp_VMSetError,
4264 pdmR3DevHlp_VMSetErrorV,
4265 pdmR3DevHlp_VMSetRuntimeError,
4266 pdmR3DevHlp_VMSetRuntimeErrorV,
4267 pdmR3DevHlp_DBGFStopV,
4268 pdmR3DevHlp_DBGFInfoRegister,
4269 pdmR3DevHlp_DBGFInfoRegisterArgv,
4270 pdmR3DevHlp_DBGFRegRegister,
4271 pdmR3DevHlp_DBGFTraceBuf,
4272 pdmR3DevHlp_STAMRegister,
4273 pdmR3DevHlp_STAMRegisterF,
4274 pdmR3DevHlp_STAMRegisterV,
4275 pdmR3DevHlp_PCIRegister,
4276 pdmR3DevHlp_PCIRegisterMsi,
4277 pdmR3DevHlp_PCIIORegionRegister,
4278 pdmR3DevHlp_PCIInterceptConfigAccesses,
4279 pdmR3DevHlp_PCIConfigWrite,
4280 pdmR3DevHlp_PCIConfigRead,
4281 pdmR3DevHlp_PCIPhysRead,
4282 pdmR3DevHlp_PCIPhysWrite,
4283 pdmR3DevHlp_PCISetIrq,
4284 pdmR3DevHlp_PCISetIrqNoWait,
4285 pdmR3DevHlp_ISASetIrq,
4286 pdmR3DevHlp_ISASetIrqNoWait,
4287 pdmR3DevHlp_IoApicSendMsi,
4288 pdmR3DevHlp_DriverAttach,
4289 pdmR3DevHlp_DriverDetach,
4290 pdmR3DevHlp_QueueCreate,
4291 pdmR3DevHlp_CritSectInit,
4292 pdmR3DevHlp_CritSectGetNop,
4293 pdmR3DevHlp_CritSectGetNopR0,
4294 pdmR3DevHlp_CritSectGetNopRC,
4295 pdmR3DevHlp_SetDeviceCritSect,
4296 pdmR3DevHlp_CritSectYield,
4297 pdmR3DevHlp_CritSectEnter,
4298 pdmR3DevHlp_CritSectEnterDebug,
4299 pdmR3DevHlp_CritSectTryEnter,
4300 pdmR3DevHlp_CritSectTryEnterDebug,
4301 pdmR3DevHlp_CritSectLeave,
4302 pdmR3DevHlp_CritSectIsOwner,
4303 pdmR3DevHlp_CritSectIsInitialized,
4304 pdmR3DevHlp_CritSectHasWaiters,
4305 pdmR3DevHlp_CritSectGetRecursion,
4306 pdmR3DevHlp_ThreadCreate,
4307 pdmR3DevHlp_SetAsyncNotification,
4308 pdmR3DevHlp_AsyncNotificationCompleted,
4309 pdmR3DevHlp_RTCRegister,
4310 pdmR3DevHlp_PCIBusRegister,
4311 pdmR3DevHlp_PICRegister,
4312 pdmR3DevHlp_APICRegister,
4313 pdmR3DevHlp_IOAPICRegister,
4314 pdmR3DevHlp_HPETRegister,
4315 pdmR3DevHlp_PciRawRegister,
4316 pdmR3DevHlp_DMACRegister,
4317 pdmR3DevHlp_DMARegister,
4318 pdmR3DevHlp_DMAReadMemory,
4319 pdmR3DevHlp_DMAWriteMemory,
4320 pdmR3DevHlp_DMASetDREQ,
4321 pdmR3DevHlp_DMAGetChannelMode,
4322 pdmR3DevHlp_DMASchedule,
4323 pdmR3DevHlp_CMOSWrite,
4324 pdmR3DevHlp_CMOSRead,
4325 pdmR3DevHlp_AssertEMT,
4326 pdmR3DevHlp_AssertOther,
4327 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4328 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4329 pdmR3DevHlp_CallR0,
4330 pdmR3DevHlp_VMGetSuspendReason,
4331 pdmR3DevHlp_VMGetResumeReason,
4332 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4333 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4334 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4335 pdmR3DevHlp_MMIOExChangeRegionNo,
4336 0,
4337 0,
4338 0,
4339 0,
4340 0,
4341 0,
4342 0,
4343 0,
4344 0,
4345 0,
4346 pdmR3DevHlp_GetUVM,
4347 pdmR3DevHlp_GetVM,
4348 pdmR3DevHlp_GetVMCPU,
4349 pdmR3DevHlp_GetCurrentCpuId,
4350 pdmR3DevHlp_RegisterVMMDevHeap,
4351 pdmR3DevHlp_FirmwareRegister,
4352 pdmR3DevHlp_VMReset,
4353 pdmR3DevHlp_VMSuspend,
4354 pdmR3DevHlp_VMSuspendSaveAndPowerOff,
4355 pdmR3DevHlp_VMPowerOff,
4356 pdmR3DevHlp_A20IsEnabled,
4357 pdmR3DevHlp_A20Set,
4358 pdmR3DevHlp_GetCpuId,
4359 pdmR3DevHlp_TMTimeVirtGet,
4360 pdmR3DevHlp_TMTimeVirtGetFreq,
4361 pdmR3DevHlp_TMTimeVirtGetNano,
4362 pdmR3DevHlp_GetSupDrvSession,
4363 pdmR3DevHlp_QueryGenericUserObject,
4364 PDM_DEVHLPR3_VERSION /* the end */
4365};
4366
4367
4368
4369
4370/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
4371static DECLCALLBACK(PUVM) pdmR3DevHlp_Untrusted_GetUVM(PPDMDEVINS pDevIns)
4372{
4373 PDMDEV_ASSERT_DEVINS(pDevIns);
4374 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4375 return NULL;
4376}
4377
4378
4379/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
4380static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
4381{
4382 PDMDEV_ASSERT_DEVINS(pDevIns);
4383 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4384 return NULL;
4385}
4386
4387
4388/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
4389static DECLCALLBACK(PVMCPU) pdmR3DevHlp_Untrusted_GetVMCPU(PPDMDEVINS pDevIns)
4390{
4391 PDMDEV_ASSERT_DEVINS(pDevIns);
4392 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4393 return NULL;
4394}
4395
4396
4397/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
4398static DECLCALLBACK(VMCPUID) pdmR3DevHlp_Untrusted_GetCurrentCpuId(PPDMDEVINS pDevIns)
4399{
4400 PDMDEV_ASSERT_DEVINS(pDevIns);
4401 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4402 return NIL_VMCPUID;
4403}
4404
4405
4406/** @interface_method_impl{PDMDEVHLPR3,pfnRegisterVMMDevHeap} */
4407static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys,
4408 RTR3PTR pvHeap, unsigned cbHeap)
4409{
4410 PDMDEV_ASSERT_DEVINS(pDevIns);
4411 NOREF(GCPhys); NOREF(pvHeap); NOREF(cbHeap);
4412 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4413 return VERR_ACCESS_DENIED;
4414}
4415
4416
4417/** @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister} */
4418static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
4419{
4420 PDMDEV_ASSERT_DEVINS(pDevIns);
4421 NOREF(pFwReg); NOREF(ppFwHlp);
4422 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4423 return VERR_ACCESS_DENIED;
4424}
4425
4426
4427/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
4428static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
4429{
4430 PDMDEV_ASSERT_DEVINS(pDevIns); NOREF(fFlags);
4431 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4432 return VERR_ACCESS_DENIED;
4433}
4434
4435
4436/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
4437static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
4438{
4439 PDMDEV_ASSERT_DEVINS(pDevIns);
4440 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4441 return VERR_ACCESS_DENIED;
4442}
4443
4444
4445/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
4446static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
4447{
4448 PDMDEV_ASSERT_DEVINS(pDevIns);
4449 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4450 return VERR_ACCESS_DENIED;
4451}
4452
4453
4454/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
4455static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
4456{
4457 PDMDEV_ASSERT_DEVINS(pDevIns);
4458 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4459 return VERR_ACCESS_DENIED;
4460}
4461
4462
4463/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
4464static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
4465{
4466 PDMDEV_ASSERT_DEVINS(pDevIns);
4467 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4468 return false;
4469}
4470
4471
4472/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
4473static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
4474{
4475 PDMDEV_ASSERT_DEVINS(pDevIns);
4476 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4477 NOREF(fEnable);
4478}
4479
4480
4481/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
4482static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
4483 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
4484{
4485 PDMDEV_ASSERT_DEVINS(pDevIns);
4486 NOREF(iLeaf); NOREF(pEax); NOREF(pEbx); NOREF(pEcx); NOREF(pEdx);
4487 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4488}
4489
4490
4491/** @interface_method_impl{PDMDEVHLPR3,pfnGetSupDrvSession} */
4492static DECLCALLBACK(PSUPDRVSESSION) pdmR3DevHlp_Untrusted_GetSupDrvSession(PPDMDEVINS pDevIns)
4493{
4494 PDMDEV_ASSERT_DEVINS(pDevIns);
4495 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4496 return (PSUPDRVSESSION)0;
4497}
4498
4499
4500/** @interface_method_impl{PDMDEVHLPR3,pfnQueryGenericUserObject} */
4501static DECLCALLBACK(void *) pdmR3DevHlp_Untrusted_QueryGenericUserObject(PPDMDEVINS pDevIns, PCRTUUID pUuid)
4502{
4503 PDMDEV_ASSERT_DEVINS(pDevIns);
4504 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d %RTuuid\n",
4505 pDevIns->pReg->szName, pDevIns->iInstance, pUuid));
4506 return NULL;
4507}
4508
4509
4510/**
4511 * The device helper structure for non-trusted devices.
4512 */
4513const PDMDEVHLPR3 g_pdmR3DevHlpUnTrusted =
4514{
4515 PDM_DEVHLPR3_VERSION,
4516 pdmR3DevHlp_IoPortCreateEx,
4517 pdmR3DevHlp_IoPortMap,
4518 pdmR3DevHlp_IoPortUnmap,
4519 pdmR3DevHlp_IOPortRegister,
4520 pdmR3DevHlp_IOPortRegisterRC,
4521 pdmR3DevHlp_IOPortRegisterR0,
4522 pdmR3DevHlp_IOPortDeregister,
4523 pdmR3DevHlp_MmioCreateEx,
4524 pdmR3DevHlp_MmioMap,
4525 pdmR3DevHlp_MmioUnmap,
4526 pdmR3DevHlp_MmioReduce,
4527 pdmR3DevHlp_MMIORegister,
4528 pdmR3DevHlp_MMIORegisterRC,
4529 pdmR3DevHlp_MMIORegisterR0,
4530 pdmR3DevHlp_MMIODeregister,
4531 pdmR3DevHlp_MMIO2Register,
4532 pdmR3DevHlp_MMIOExPreRegister,
4533 pdmR3DevHlp_MMIOExDeregister,
4534 pdmR3DevHlp_MMIOExMap,
4535 pdmR3DevHlp_MMIOExUnmap,
4536 pdmR3DevHlp_MMIOExReduce,
4537 pdmR3DevHlp_MMHyperMapMMIO2,
4538 pdmR3DevHlp_MMIO2MapKernel,
4539 pdmR3DevHlp_ROMRegister,
4540 pdmR3DevHlp_ROMProtectShadow,
4541 pdmR3DevHlp_SSMRegister,
4542 SSMR3PutStruct,
4543 SSMR3PutStructEx,
4544 SSMR3PutBool,
4545 SSMR3PutU8,
4546 SSMR3PutS8,
4547 SSMR3PutU16,
4548 SSMR3PutS16,
4549 SSMR3PutU32,
4550 SSMR3PutS32,
4551 SSMR3PutU64,
4552 SSMR3PutS64,
4553 SSMR3PutU128,
4554 SSMR3PutS128,
4555 SSMR3PutUInt,
4556 SSMR3PutSInt,
4557 SSMR3PutGCUInt,
4558 SSMR3PutGCUIntReg,
4559 SSMR3PutGCPhys32,
4560 SSMR3PutGCPhys64,
4561 SSMR3PutGCPhys,
4562 SSMR3PutGCPtr,
4563 SSMR3PutGCUIntPtr,
4564 SSMR3PutRCPtr,
4565 SSMR3PutIOPort,
4566 SSMR3PutSel,
4567 SSMR3PutMem,
4568 SSMR3PutStrZ,
4569 SSMR3GetStruct,
4570 SSMR3GetStructEx,
4571 SSMR3GetBool,
4572 SSMR3GetU8,
4573 SSMR3GetS8,
4574 SSMR3GetU16,
4575 SSMR3GetS16,
4576 SSMR3GetU32,
4577 SSMR3GetS32,
4578 SSMR3GetU64,
4579 SSMR3GetS64,
4580 SSMR3GetU128,
4581 SSMR3GetS128,
4582 SSMR3GetUInt,
4583 SSMR3GetSInt,
4584 SSMR3GetGCUInt,
4585 SSMR3GetGCUIntReg,
4586 SSMR3GetGCPhys32,
4587 SSMR3GetGCPhys64,
4588 SSMR3GetGCPhys,
4589 SSMR3GetGCPtr,
4590 SSMR3GetGCUIntPtr,
4591 SSMR3GetRCPtr,
4592 SSMR3GetIOPort,
4593 SSMR3GetSel,
4594 SSMR3GetMem,
4595 SSMR3GetStrZ,
4596 SSMR3GetStrZEx,
4597 SSMR3Skip,
4598 SSMR3SkipToEndOfUnit,
4599 SSMR3SetLoadError,
4600 SSMR3SetLoadErrorV,
4601 SSMR3SetCfgError,
4602 SSMR3SetCfgErrorV,
4603 SSMR3HandleGetStatus,
4604 SSMR3HandleGetAfter,
4605 SSMR3HandleIsLiveSave,
4606 SSMR3HandleMaxDowntime,
4607 SSMR3HandleHostBits,
4608 SSMR3HandleRevision,
4609 SSMR3HandleVersion,
4610 pdmR3DevHlp_TMTimerCreate,
4611 pdmR3DevHlp_TimerCreate,
4612 pdmR3DevHlp_TimerToPtr,
4613 pdmR3DevHlp_TimerFromMicro,
4614 pdmR3DevHlp_TimerFromMilli,
4615 pdmR3DevHlp_TimerFromNano,
4616 pdmR3DevHlp_TimerGet,
4617 pdmR3DevHlp_TimerGetFreq,
4618 pdmR3DevHlp_TimerGetNano,
4619 pdmR3DevHlp_TimerIsActive,
4620 pdmR3DevHlp_TimerIsLockOwner,
4621 pdmR3DevHlp_TimerLock,
4622 pdmR3DevHlp_TimerSet,
4623 pdmR3DevHlp_TimerSetFrequencyHint,
4624 pdmR3DevHlp_TimerSetMicro,
4625 pdmR3DevHlp_TimerSetMillies,
4626 pdmR3DevHlp_TimerSetNano,
4627 pdmR3DevHlp_TimerSetRelative,
4628 pdmR3DevHlp_TimerStop,
4629 pdmR3DevHlp_TimerUnlock,
4630 pdmR3DevHlp_TimerSave,
4631 pdmR3DevHlp_TimerLoad,
4632 pdmR3DevHlp_TMUtcNow,
4633 CFGMR3Exists,
4634 CFGMR3QueryType,
4635 CFGMR3QuerySize,
4636 CFGMR3QueryInteger,
4637 CFGMR3QueryIntegerDef,
4638 CFGMR3QueryString,
4639 CFGMR3QueryStringDef,
4640 CFGMR3QueryBytes,
4641 CFGMR3QueryU64,
4642 CFGMR3QueryU64Def,
4643 CFGMR3QueryS64,
4644 CFGMR3QueryS64Def,
4645 CFGMR3QueryU32,
4646 CFGMR3QueryU32Def,
4647 CFGMR3QueryS32,
4648 CFGMR3QueryS32Def,
4649 CFGMR3QueryU16,
4650 CFGMR3QueryU16Def,
4651 CFGMR3QueryS16,
4652 CFGMR3QueryS16Def,
4653 CFGMR3QueryU8,
4654 CFGMR3QueryU8Def,
4655 CFGMR3QueryS8,
4656 CFGMR3QueryS8Def,
4657 CFGMR3QueryBool,
4658 CFGMR3QueryBoolDef,
4659 CFGMR3QueryPort,
4660 CFGMR3QueryPortDef,
4661 CFGMR3QueryUInt,
4662 CFGMR3QueryUIntDef,
4663 CFGMR3QuerySInt,
4664 CFGMR3QuerySIntDef,
4665 CFGMR3QueryPtr,
4666 CFGMR3QueryPtrDef,
4667 CFGMR3QueryGCPtr,
4668 CFGMR3QueryGCPtrDef,
4669 CFGMR3QueryGCPtrU,
4670 CFGMR3QueryGCPtrUDef,
4671 CFGMR3QueryGCPtrS,
4672 CFGMR3QueryGCPtrSDef,
4673 CFGMR3QueryStringAlloc,
4674 CFGMR3QueryStringAllocDef,
4675 CFGMR3GetParent,
4676 CFGMR3GetChild,
4677 CFGMR3GetChildF,
4678 CFGMR3GetChildFV,
4679 CFGMR3GetFirstChild,
4680 CFGMR3GetNextChild,
4681 CFGMR3GetName,
4682 CFGMR3GetNameLen,
4683 CFGMR3AreChildrenValid,
4684 CFGMR3GetFirstValue,
4685 CFGMR3GetNextValue,
4686 CFGMR3GetValueName,
4687 CFGMR3GetValueNameLen,
4688 CFGMR3GetValueType,
4689 CFGMR3AreValuesValid,
4690 CFGMR3ValidateConfig,
4691 pdmR3DevHlp_PhysRead,
4692 pdmR3DevHlp_PhysWrite,
4693 pdmR3DevHlp_PhysGCPhys2CCPtr,
4694 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4695 pdmR3DevHlp_PhysReleasePageMappingLock,
4696 pdmR3DevHlp_PhysReadGCVirt,
4697 pdmR3DevHlp_PhysWriteGCVirt,
4698 pdmR3DevHlp_PhysGCPtr2GCPhys,
4699 pdmR3DevHlp_MMHeapAlloc,
4700 pdmR3DevHlp_MMHeapAllocZ,
4701 pdmR3DevHlp_MMHeapFree,
4702 pdmR3DevHlp_VMState,
4703 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4704 pdmR3DevHlp_VMSetError,
4705 pdmR3DevHlp_VMSetErrorV,
4706 pdmR3DevHlp_VMSetRuntimeError,
4707 pdmR3DevHlp_VMSetRuntimeErrorV,
4708 pdmR3DevHlp_DBGFStopV,
4709 pdmR3DevHlp_DBGFInfoRegister,
4710 pdmR3DevHlp_DBGFInfoRegisterArgv,
4711 pdmR3DevHlp_DBGFRegRegister,
4712 pdmR3DevHlp_DBGFTraceBuf,
4713 pdmR3DevHlp_STAMRegister,
4714 pdmR3DevHlp_STAMRegisterF,
4715 pdmR3DevHlp_STAMRegisterV,
4716 pdmR3DevHlp_PCIRegister,
4717 pdmR3DevHlp_PCIRegisterMsi,
4718 pdmR3DevHlp_PCIIORegionRegister,
4719 pdmR3DevHlp_PCIInterceptConfigAccesses,
4720 pdmR3DevHlp_PCIConfigWrite,
4721 pdmR3DevHlp_PCIConfigRead,
4722 pdmR3DevHlp_PCIPhysRead,
4723 pdmR3DevHlp_PCIPhysWrite,
4724 pdmR3DevHlp_PCISetIrq,
4725 pdmR3DevHlp_PCISetIrqNoWait,
4726 pdmR3DevHlp_ISASetIrq,
4727 pdmR3DevHlp_ISASetIrqNoWait,
4728 pdmR3DevHlp_IoApicSendMsi,
4729 pdmR3DevHlp_DriverAttach,
4730 pdmR3DevHlp_DriverDetach,
4731 pdmR3DevHlp_QueueCreate,
4732 pdmR3DevHlp_CritSectInit,
4733 pdmR3DevHlp_CritSectGetNop,
4734 pdmR3DevHlp_CritSectGetNopR0,
4735 pdmR3DevHlp_CritSectGetNopRC,
4736 pdmR3DevHlp_SetDeviceCritSect,
4737 pdmR3DevHlp_CritSectYield,
4738 pdmR3DevHlp_CritSectEnter,
4739 pdmR3DevHlp_CritSectEnterDebug,
4740 pdmR3DevHlp_CritSectTryEnter,
4741 pdmR3DevHlp_CritSectTryEnterDebug,
4742 pdmR3DevHlp_CritSectLeave,
4743 pdmR3DevHlp_CritSectIsOwner,
4744 pdmR3DevHlp_CritSectIsInitialized,
4745 pdmR3DevHlp_CritSectHasWaiters,
4746 pdmR3DevHlp_CritSectGetRecursion,
4747 pdmR3DevHlp_ThreadCreate,
4748 pdmR3DevHlp_SetAsyncNotification,
4749 pdmR3DevHlp_AsyncNotificationCompleted,
4750 pdmR3DevHlp_RTCRegister,
4751 pdmR3DevHlp_PCIBusRegister,
4752 pdmR3DevHlp_PICRegister,
4753 pdmR3DevHlp_APICRegister,
4754 pdmR3DevHlp_IOAPICRegister,
4755 pdmR3DevHlp_HPETRegister,
4756 pdmR3DevHlp_PciRawRegister,
4757 pdmR3DevHlp_DMACRegister,
4758 pdmR3DevHlp_DMARegister,
4759 pdmR3DevHlp_DMAReadMemory,
4760 pdmR3DevHlp_DMAWriteMemory,
4761 pdmR3DevHlp_DMASetDREQ,
4762 pdmR3DevHlp_DMAGetChannelMode,
4763 pdmR3DevHlp_DMASchedule,
4764 pdmR3DevHlp_CMOSWrite,
4765 pdmR3DevHlp_CMOSRead,
4766 pdmR3DevHlp_AssertEMT,
4767 pdmR3DevHlp_AssertOther,
4768 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4769 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4770 pdmR3DevHlp_CallR0,
4771 pdmR3DevHlp_VMGetSuspendReason,
4772 pdmR3DevHlp_VMGetResumeReason,
4773 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4774 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4775 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4776 pdmR3DevHlp_MMIOExChangeRegionNo,
4777 0,
4778 0,
4779 0,
4780 0,
4781 0,
4782 0,
4783 0,
4784 0,
4785 0,
4786 0,
4787 pdmR3DevHlp_Untrusted_GetUVM,
4788 pdmR3DevHlp_Untrusted_GetVM,
4789 pdmR3DevHlp_Untrusted_GetVMCPU,
4790 pdmR3DevHlp_Untrusted_GetCurrentCpuId,
4791 pdmR3DevHlp_Untrusted_RegisterVMMDevHeap,
4792 pdmR3DevHlp_Untrusted_FirmwareRegister,
4793 pdmR3DevHlp_Untrusted_VMReset,
4794 pdmR3DevHlp_Untrusted_VMSuspend,
4795 pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff,
4796 pdmR3DevHlp_Untrusted_VMPowerOff,
4797 pdmR3DevHlp_Untrusted_A20IsEnabled,
4798 pdmR3DevHlp_Untrusted_A20Set,
4799 pdmR3DevHlp_Untrusted_GetCpuId,
4800 pdmR3DevHlp_TMTimeVirtGet,
4801 pdmR3DevHlp_TMTimeVirtGetFreq,
4802 pdmR3DevHlp_TMTimeVirtGetNano,
4803 pdmR3DevHlp_Untrusted_GetSupDrvSession,
4804 pdmR3DevHlp_Untrusted_QueryGenericUserObject,
4805 PDM_DEVHLPR3_VERSION /* the end */
4806};
4807
4808
4809
4810/**
4811 * Queue consumer callback for internal component.
4812 *
4813 * @returns Success indicator.
4814 * If false the item will not be removed and the flushing will stop.
4815 * @param pVM The cross context VM structure.
4816 * @param pItem The item to consume. Upon return this item will be freed.
4817 */
4818DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
4819{
4820 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
4821 LogFlow(("pdmR3DevHlpQueueConsumer: enmOp=%d pDevIns=%p\n", pTask->enmOp, pTask->pDevInsR3));
4822 switch (pTask->enmOp)
4823 {
4824 case PDMDEVHLPTASKOP_ISA_SET_IRQ:
4825 PDMIsaSetIrq(pVM, pTask->u.IsaSetIRQ.iIrq, pTask->u.IsaSetIRQ.iLevel, pTask->u.IsaSetIRQ.uTagSrc);
4826 break;
4827
4828 case PDMDEVHLPTASKOP_PCI_SET_IRQ:
4829 {
4830 /* Same as pdmR3DevHlp_PCISetIrq, except we've got a tag already. */
4831 PPDMPCIDEV pPciDev = pTask->u.PciSetIRQ.pPciDevR3;
4832 if (pPciDev)
4833 {
4834 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
4835 AssertBreak(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
4836 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
4837
4838 pdmLock(pVM);
4839 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, pTask->u.PciSetIRQ.iIrq,
4840 pTask->u.PciSetIRQ.iLevel, pTask->u.PciSetIRQ.uTagSrc);
4841 pdmUnlock(pVM);
4842 }
4843 else
4844 AssertReleaseMsgFailed(("No PCI device registered!\n"));
4845 break;
4846 }
4847
4848 case PDMDEVHLPTASKOP_IOAPIC_SET_IRQ:
4849 PDMIoApicSetIrq(pVM, pTask->u.IoApicSetIRQ.iIrq, pTask->u.IoApicSetIRQ.iLevel, pTask->u.IoApicSetIRQ.uTagSrc);
4850 break;
4851
4852 default:
4853 AssertReleaseMsgFailed(("Invalid operation %d\n", pTask->enmOp));
4854 break;
4855 }
4856 return true;
4857}
4858
4859/** @} */
4860
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