VirtualBox

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

最後變更 在這個檔案從80911是 80722,由 vboxsync 提交於 6 年 前

PDM,PCI: More PDMPCIDEV related refactoring work, mainly concerned with eliminating unnecessary pointers. bugref:9218

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 190.3 KB
 
1/* $Id: PDMDevHlp.cpp 80722 2019-09-11 09:21:47Z 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.alldomusa.eu.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, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,
102 PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING 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 idxDevCfg, 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} idxDevCfg=%d fFlags=%#x uPciDevNo=%#x uPciFunNo=%#x pszName=%p:{%s}\n",
1653 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->abConfig, idxDevCfg, 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(idxDevCfg < 256 || idxDevCfg == PDMPCIDEVREG_CFG_NEXT,
1668 ("'%s'/%d: Invalid config selector: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, idxDevCfg),
1669 VERR_OUT_OF_RANGE);
1670 AssertLogRelMsgReturn( uPciDevNo < 32
1671 || uPciDevNo == PDMPCIDEVREG_DEV_NO_FIRST_UNUSED
1672 || uPciDevNo == PDMPCIDEVREG_DEV_NO_SAME_AS_PREV,
1673 ("'%s'/%d: Invalid PCI device number: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, uPciDevNo),
1674 VERR_INVALID_PARAMETER);
1675 AssertLogRelMsgReturn( uPciFunNo < 8
1676 || uPciFunNo == PDMPCIDEVREG_FUN_NO_FIRST_UNUSED,
1677 ("'%s'/%d: Invalid PCI funcion number: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, uPciFunNo),
1678 VERR_INVALID_PARAMETER);
1679 AssertLogRelMsgReturn(!(fFlags & ~PDMPCIDEVREG_F_VALID_MASK),
1680 ("'%s'/%d: Invalid flags: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, fFlags),
1681 VERR_INVALID_FLAGS);
1682 if (!pszName)
1683 pszName = pDevIns->pReg->szName;
1684 AssertLogRelReturn(RT_VALID_PTR(pszName), VERR_INVALID_POINTER);
1685
1686 /*
1687 * Find the last(/previous) registered PCI device (for linking and more),
1688 * checking for duplicate registration attempts while doing so.
1689 */
1690 uint32_t idxDevCfgNext = 0;
1691 PPDMPCIDEV pPrevPciDev = pDevIns->Internal.s.pHeadPciDevR3;
1692 while (pPrevPciDev)
1693 {
1694 AssertLogRelMsgReturn(pPrevPciDev != pPciDev,
1695 ("'%s'/%d attempted to register the same PCI device (%p) twice\n",
1696 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev),
1697 VERR_DUPLICATE);
1698 AssertLogRelMsgReturn(pPrevPciDev->Int.s.idxDevCfg != idxDevCfg,
1699 ("'%s'/%d attempted to use the same device config index (%u) twice\n",
1700 pDevIns->pReg->szName, pDevIns->iInstance, idxDevCfg),
1701 VERR_ALREADY_LOADED);
1702 if (pPrevPciDev->Int.s.idxDevCfg >= idxDevCfgNext)
1703 idxDevCfgNext = pPrevPciDev->Int.s.idxDevCfg + 1;
1704
1705 if (!pPrevPciDev->Int.s.pNextR3)
1706 break;
1707 pPrevPciDev = pPrevPciDev->Int.s.pNextR3;
1708 }
1709
1710 /*
1711 * Resolve the PCI configuration node for the device. The default (zero'th)
1712 * is the same as the PDM device, the rest are "PciCfg1..255" CFGM sub-nodes.
1713 */
1714 if (idxDevCfg == PDMPCIDEVREG_CFG_NEXT)
1715 {
1716 idxDevCfg = idxDevCfgNext;
1717 AssertLogRelMsgReturn(idxDevCfg < 256, ("'%s'/%d: PDMPCIDEVREG_IDX_DEV_CFG_NEXT ran out of valid indexes (ends at 255)\n",
1718 pDevIns->pReg->szName, pDevIns->iInstance),
1719 VERR_OUT_OF_RANGE);
1720 }
1721
1722 PCFGMNODE pCfg = pDevIns->Internal.s.pCfgHandle;
1723 if (idxDevCfg != 0)
1724 pCfg = CFGMR3GetChildF(pDevIns->Internal.s.pCfgHandle, "PciCfg%u", idxDevCfg);
1725
1726 /*
1727 * We resolve PDMPCIDEVREG_DEV_NO_SAME_AS_PREV, the PCI bus handles
1728 * PDMPCIDEVREG_DEV_NO_FIRST_UNUSED and PDMPCIDEVREG_FUN_NO_FIRST_UNUSED.
1729 */
1730 uint8_t const uPciDevNoRaw = uPciDevNo;
1731 uint32_t uDefPciBusNo = 0;
1732 if (uPciDevNo == PDMPCIDEVREG_DEV_NO_SAME_AS_PREV)
1733 {
1734 if (pPrevPciDev)
1735 {
1736 uPciDevNo = pPrevPciDev->uDevFn >> 3;
1737 uDefPciBusNo = pPrevPciDev->Int.s.idxPdmBus;
1738 }
1739 else
1740 {
1741 /* Look for PCI device registered with an earlier device instance so we can more
1742 easily have multiple functions spanning multiple PDM device instances. */
1743 PPDMPCIDEV pOtherPciDev = NULL;
1744 PPDMDEVINS pPrevIns = pDevIns->Internal.s.pDevR3->pInstances;
1745 while (pPrevIns != pDevIns && pPrevIns)
1746 {
1747 pOtherPciDev = pPrevIns->Internal.s.pHeadPciDevR3;
1748 pPrevIns = pPrevIns->Internal.s.pNextR3;
1749 }
1750 Assert(pPrevIns == pDevIns);
1751 AssertLogRelMsgReturn(pOtherPciDev,
1752 ("'%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",
1753 pDevIns->pReg->szName, pDevIns->iInstance),
1754 VERR_WRONG_ORDER);
1755
1756 while (pOtherPciDev->Int.s.pNextR3)
1757 pOtherPciDev = pOtherPciDev->Int.s.pNextR3;
1758 uPciDevNo = pOtherPciDev->uDevFn >> 3;
1759 uDefPciBusNo = pOtherPciDev->Int.s.idxPdmBus;
1760 }
1761 }
1762
1763 /*
1764 * Choose the PCI bus for the device.
1765 *
1766 * This is simple. If the device was configured for a particular bus, the PCIBusNo
1767 * configuration value will be set. If not the default bus is 0.
1768 */
1769 /** @cfgm{/Devices/NAME/XX/[PciCfgYY/]PCIBusNo, uint8_t, 0, 7, 0}
1770 * Selects the PCI bus number of a device. The default value isn't necessarily
1771 * zero if the device is registered using PDMPCIDEVREG_DEV_NO_SAME_AS_PREV, it
1772 * will then also inherit the bus number from the previously registered device.
1773 */
1774 uint8_t u8Bus;
1775 int rc = CFGMR3QueryU8Def(pCfg, "PCIBusNo", &u8Bus, (uint8_t)uDefPciBusNo);
1776 AssertLogRelMsgRCReturn(rc, ("Configuration error: PCIBusNo query failed with rc=%Rrc (%s/%d)\n",
1777 rc, pDevIns->pReg->szName, pDevIns->iInstance), rc);
1778 AssertLogRelMsgReturn(u8Bus < RT_ELEMENTS(pVM->pdm.s.aPciBuses),
1779 ("Configuration error: PCIBusNo=%d, max is %d. (%s/%d)\n", u8Bus,
1780 RT_ELEMENTS(pVM->pdm.s.aPciBuses), pDevIns->pReg->szName, pDevIns->iInstance),
1781 VERR_PDM_NO_PCI_BUS);
1782 pPciDev->Int.s.idxPdmBus = u8Bus;
1783 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[u8Bus];
1784 if (pBus->pDevInsR3)
1785 {
1786 /*
1787 * Check the configuration for PCI device and function assignment.
1788 */
1789 /** @cfgm{/Devices/NAME/XX/[PciCfgYY/]PCIDeviceNo, uint8_t, 0, 31}
1790 * Overrides the default PCI device number of a device.
1791 */
1792 uint8_t uCfgDevice;
1793 rc = CFGMR3QueryU8(pCfg, "PCIDeviceNo", &uCfgDevice);
1794 if (RT_SUCCESS(rc))
1795 {
1796 AssertMsgReturn(uCfgDevice <= 31,
1797 ("Configuration error: PCIDeviceNo=%d, max is 31. (%s/%d/%d)\n",
1798 uCfgDevice, pDevIns->pReg->szName, pDevIns->iInstance, idxDevCfg),
1799 VERR_PDM_BAD_PCI_CONFIG);
1800 uPciDevNo = uCfgDevice;
1801 }
1802 else
1803 AssertMsgReturn(rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT,
1804 ("Configuration error: PCIDeviceNo query failed with rc=%Rrc (%s/%d/%d)\n",
1805 rc, pDevIns->pReg->szName, pDevIns->iInstance, idxDevCfg),
1806 rc);
1807
1808 /** @cfgm{/Devices/NAME/XX/[PciCfgYY/]PCIFunctionNo, uint8_t, 0, 7}
1809 * Overrides the default PCI function number of a device.
1810 */
1811 uint8_t uCfgFunction;
1812 rc = CFGMR3QueryU8(pCfg, "PCIFunctionNo", &uCfgFunction);
1813 if (RT_SUCCESS(rc))
1814 {
1815 AssertMsgReturn(uCfgFunction <= 7,
1816 ("Configuration error: PCIFunctionNo=%#x, max is 7. (%s/%d/%d)\n",
1817 uCfgFunction, pDevIns->pReg->szName, pDevIns->iInstance, idxDevCfg),
1818 VERR_PDM_BAD_PCI_CONFIG);
1819 uPciFunNo = uCfgFunction;
1820 }
1821 else
1822 AssertMsgReturn(rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT,
1823 ("Configuration error: PCIFunctionNo query failed with rc=%Rrc (%s/%d/%d)\n",
1824 rc, pDevIns->pReg->szName, pDevIns->iInstance, idxDevCfg),
1825 rc);
1826
1827
1828 /*
1829 * Initialize the internal data. We only do the wipe and the members
1830 * owned by PDM, the PCI bus does the rest in the registration call.
1831 */
1832 RT_ZERO(pPciDev->Int);
1833
1834 pPciDev->Int.s.idxDevCfg = idxDevCfg;
1835 pPciDev->Int.s.fReassignableDevNo = uPciDevNoRaw >= VBOX_PCI_MAX_DEVICES;
1836 pPciDev->Int.s.fReassignableFunNo = uPciFunNo >= VBOX_PCI_MAX_FUNCTIONS;
1837 pPciDev->Int.s.pDevInsR3 = pDevIns;
1838 pPciDev->Int.s.idxPdmBus = u8Bus;
1839
1840 /* Set some of the public members too. */
1841 pPciDev->pszNameR3 = pszName;
1842
1843 /*
1844 * Call the pci bus device to do the actual registration.
1845 */
1846 pdmLock(pVM);
1847 rc = pBus->pfnRegisterR3(pBus->pDevInsR3, pPciDev, fFlags, uPciDevNo, uPciFunNo, pszName);
1848 pdmUnlock(pVM);
1849 if (RT_SUCCESS(rc))
1850 {
1851
1852 /*
1853 * Link it.
1854 */
1855 if (pPrevPciDev)
1856 {
1857 Assert(!pPrevPciDev->Int.s.pNextR3);
1858 pPrevPciDev->Int.s.pNextR3 = pPciDev;
1859 pPrevPciDev->Int.s.pNextR0 = NIL_RTRCPTR;
1860 }
1861 else
1862 {
1863 Assert(!pDevIns->Internal.s.pHeadPciDevR3);
1864 pDevIns->Internal.s.pHeadPciDevR3 = pPciDev;
1865 }
1866
1867 Assert(RT_BOOL(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED) == pDevIns->fR0Enabled);
1868 if ( (pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED)
1869 && !(pDevIns->Internal.s.pDevR3->pReg->fFlags & PDM_DEVREG_FLAGS_NEW_STYLE))
1870 {
1871 PDMDEVICECOMPATREGPCIDEVREQ Req;
1872 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
1873 Req.Hdr.cbReq = sizeof(Req);
1874 Req.idxR0Device = pDevIns->Internal.s.idxR0Device;
1875 Req.pDevInsR3 = pDevIns;
1876 Req.pPciDevR3 = pPciDev;
1877 rc = VMMR3CallR0(pVM, VMMR0_DO_PDM_DEVICE_COMPAT_REG_PCIDEV, 0, &Req.Hdr);
1878 AssertLogRelRCReturn(rc, rc);
1879 }
1880
1881 Log(("PDM: Registered device '%s'/%d as PCI device %d on bus %d\n",
1882 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->uDevFn, pBus->iBus));
1883 }
1884 }
1885 else
1886 {
1887 AssertLogRelMsgFailed(("Configuration error: No PCI bus available. This could be related to init order too!\n"));
1888 rc = VERR_PDM_NO_PCI_BUS;
1889 }
1890
1891 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1892 return rc;
1893}
1894
1895
1896/** @interface_method_impl{PDMDEVHLPR3,pfnPCIRegisterMsi} */
1897static DECLCALLBACK(int) pdmR3DevHlp_PCIRegisterMsi(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, PPDMMSIREG pMsiReg)
1898{
1899 PDMDEV_ASSERT_DEVINS(pDevIns);
1900 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1901 pPciDev = pDevIns->Internal.s.pHeadPciDevR3;
1902 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1903 LogFlow(("pdmR3DevHlp_PCIRegisterMsi: caller='%s'/%d: pPciDev=%p:{%#x} pMsgReg=%p:{cMsiVectors=%d, cMsixVectors=%d}\n",
1904 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, pMsiReg, pMsiReg->cMsiVectors, pMsiReg->cMsixVectors));
1905
1906 AssertLogRelMsgReturn(pDevIns->pReg->cMaxPciDevices > 0,
1907 ("'%s'/%d: cMaxPciDevices is 0\n", pDevIns->pReg->szName, pDevIns->iInstance),
1908 VERR_WRONG_ORDER);
1909 AssertLogRelMsgReturn(pMsiReg->cMsixVectors <= pDevIns->pReg->cMaxMsixVectors,
1910 ("'%s'/%d: cMsixVectors=%u cMaxMsixVectors=%u\n",
1911 pDevIns->pReg->szName, pDevIns->iInstance, pMsiReg->cMsixVectors, pDevIns->pReg->cMaxMsixVectors),
1912 VERR_INVALID_FLAGS);
1913
1914 PVM pVM = pDevIns->Internal.s.pVMR3;
1915 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
1916 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_WRONG_ORDER);
1917 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
1918
1919 pdmLock(pVM);
1920 int rc;
1921 if (pBus->pfnRegisterMsiR3)
1922 rc = pBus->pfnRegisterMsiR3(pBus->pDevInsR3, pPciDev, pMsiReg);
1923 else
1924 rc = VERR_NOT_IMPLEMENTED;
1925 pdmUnlock(pVM);
1926
1927 LogFlow(("pdmR3DevHlp_PCIRegisterMsi: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1928 return rc;
1929}
1930
1931
1932/** @interface_method_impl{PDMDEVHLPR3,pfnPCIIORegionRegister} */
1933static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
1934 RTGCPHYS cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
1935{
1936 PDMDEV_ASSERT_DEVINS(pDevIns);
1937 PVM pVM = pDevIns->Internal.s.pVMR3;
1938 VM_ASSERT_EMT(pVM);
1939 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1940 pPciDev = pDevIns->Internal.s.pHeadPciDevR3;
1941 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1942 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%d cbRegion=%RGp enmType=%d pfnCallback=%p\n",
1943 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iRegion, cbRegion, enmType, pfnCallback));
1944
1945 /*
1946 * Validate input.
1947 */
1948 if (iRegion >= VBOX_PCI_NUM_REGIONS)
1949 {
1950 Assert(iRegion < VBOX_PCI_NUM_REGIONS);
1951 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (iRegion)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1952 return VERR_INVALID_PARAMETER;
1953 }
1954
1955 switch ((int)enmType)
1956 {
1957 case PCI_ADDRESS_SPACE_IO:
1958 /*
1959 * Sanity check: don't allow to register more than 32K of the PCI I/O space.
1960 */
1961 AssertLogRelMsgReturn(cbRegion <= _32K,
1962 ("caller='%s'/%d: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cbRegion),
1963 VERR_INVALID_PARAMETER);
1964 break;
1965
1966 case PCI_ADDRESS_SPACE_MEM:
1967 case PCI_ADDRESS_SPACE_MEM_PREFETCH:
1968 /*
1969 * Sanity check: Don't allow to register more than 2GB of the PCI MMIO space.
1970 */
1971 AssertLogRelMsgReturn(cbRegion <= MM_MMIO_32_MAX,
1972 ("caller='%s'/%d: %RGp (max %RGp)\n",
1973 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, (RTGCPHYS)MM_MMIO_32_MAX),
1974 VERR_OUT_OF_RANGE);
1975 break;
1976
1977 case PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM:
1978 case PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM_PREFETCH:
1979 /*
1980 * Sanity check: Don't allow to register more than 64GB of the 64-bit PCI MMIO space.
1981 */
1982 AssertLogRelMsgReturn(cbRegion <= MM_MMIO_64_MAX,
1983 ("caller='%s'/%d: %RGp (max %RGp)\n",
1984 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, MM_MMIO_64_MAX),
1985 VERR_OUT_OF_RANGE);
1986 break;
1987
1988 default:
1989 AssertMsgFailed(("enmType=%#x is unknown\n", enmType));
1990 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (enmType)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1991 return VERR_INVALID_PARAMETER;
1992 }
1993 if (!pfnCallback)
1994 {
1995 Assert(pfnCallback);
1996 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (callback)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1997 return VERR_INVALID_PARAMETER;
1998 }
1999 AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
2000
2001 /*
2002 * We're currently restricted to page aligned MMIO regions.
2003 */
2004 if ( ((enmType & ~(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM_PREFETCH)) == PCI_ADDRESS_SPACE_MEM)
2005 && cbRegion != RT_ALIGN_64(cbRegion, PAGE_SIZE))
2006 {
2007 Log(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: aligning cbRegion %RGp -> %RGp\n",
2008 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, RT_ALIGN_64(cbRegion, PAGE_SIZE)));
2009 cbRegion = RT_ALIGN_64(cbRegion, PAGE_SIZE);
2010 }
2011
2012 /*
2013 * For registering PCI MMIO memory or PCI I/O memory, the size of the region must be a power of 2!
2014 */
2015 int iLastSet = ASMBitLastSetU64(cbRegion);
2016 Assert(iLastSet > 0);
2017 uint64_t cbRegionAligned = RT_BIT_64(iLastSet - 1);
2018 if (cbRegion > cbRegionAligned)
2019 cbRegion = cbRegionAligned * 2; /* round up */
2020
2021 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2022 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_WRONG_ORDER);
2023 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2024
2025 pdmLock(pVM);
2026 int rc = pBus->pfnIORegionRegisterR3(pBus->pDevInsR3, pPciDev, iRegion, cbRegion, enmType, pfnCallback);
2027 pdmUnlock(pVM);
2028
2029 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2030 return rc;
2031}
2032
2033
2034/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetConfigCallbacks} */
2035static DECLCALLBACK(void) pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
2036 PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
2037{
2038 PDMDEV_ASSERT_DEVINS(pDevIns);
2039 PVM pVM = pDevIns->Internal.s.pVMR3;
2040 VM_ASSERT_EMT(pVM);
2041 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2042 pPciDev = pDevIns->Internal.s.pHeadPciDevR3;
2043 AssertReturnVoid(pPciDev);
2044 LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: pPciDev=%p pfnRead=%p ppfnReadOld=%p pfnWrite=%p ppfnWriteOld=%p\n",
2045 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld));
2046
2047 /*
2048 * Validate input and resolve defaults.
2049 */
2050 AssertPtr(pfnRead);
2051 AssertPtr(pfnWrite);
2052 AssertPtrNull(ppfnReadOld);
2053 AssertPtrNull(ppfnWriteOld);
2054 AssertPtrNull(pPciDev);
2055
2056 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2057 AssertReleaseReturnVoid(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
2058 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2059 AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
2060
2061 /*
2062 * Do the job.
2063 */
2064 pdmLock(pVM);
2065 pBus->pfnSetConfigCallbacksR3(pBus->pDevInsR3, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld);
2066 pdmUnlock(pVM);
2067
2068 LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
2069}
2070
2071
2072/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysRead} */
2073static DECLCALLBACK(int)
2074pdmR3DevHlp_PCIPhysRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
2075{
2076 PDMDEV_ASSERT_DEVINS(pDevIns);
2077 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2078 pPciDev = pDevIns->Internal.s.pHeadPciDevR3;
2079 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2080
2081#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
2082 /*
2083 * Just check the busmaster setting here and forward the request to the generic read helper.
2084 */
2085 if (PCIDevIsBusmaster(pPciDev))
2086 { /* likely */ }
2087 else
2088 {
2089 Log(("pdmR3DevHlp_PCIPhysRead: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbRead=%#zx\n",
2090 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbRead));
2091 memset(pvBuf, 0xff, cbRead);
2092 return VERR_PDM_NOT_PCI_BUS_MASTER;
2093 }
2094#endif
2095
2096 return pDevIns->pHlpR3->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead);
2097}
2098
2099
2100/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysWrite} */
2101static DECLCALLBACK(int)
2102pdmR3DevHlp_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
2103{
2104 PDMDEV_ASSERT_DEVINS(pDevIns);
2105 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2106 pPciDev = pDevIns->Internal.s.pHeadPciDevR3;
2107 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2108
2109#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
2110 /*
2111 * Just check the busmaster setting here and forward the request to the generic read helper.
2112 */
2113 if (PCIDevIsBusmaster(pPciDev))
2114 { /* likely */ }
2115 else
2116 {
2117 Log(("pdmR3DevHlp_PCIPhysWrite: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n",
2118 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
2119 return VERR_PDM_NOT_PCI_BUS_MASTER;
2120 }
2121#endif
2122
2123 return pDevIns->pHlpR3->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite);
2124}
2125
2126
2127/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrq} */
2128static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
2129{
2130 PDMDEV_ASSERT_DEVINS(pDevIns);
2131 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2132 pPciDev = pDevIns->Internal.s.pHeadPciDevR3;
2133 AssertReturnVoid(pPciDev);
2134 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
2135 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
2136
2137 /*
2138 * Validate input.
2139 */
2140 Assert(iIrq == 0);
2141 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
2142
2143 /*
2144 * Must have a PCI device registered!
2145 */
2146 PVM pVM = pDevIns->Internal.s.pVMR3;
2147 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2148 AssertReturnVoid(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
2149 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2150
2151 pdmLock(pVM);
2152 uint32_t uTagSrc;
2153 if (iLevel & PDM_IRQ_LEVEL_HIGH)
2154 {
2155 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
2156 if (iLevel == PDM_IRQ_LEVEL_HIGH)
2157 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2158 else
2159 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2160 }
2161 else
2162 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
2163
2164 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel, uTagSrc);
2165
2166 if (iLevel == PDM_IRQ_LEVEL_LOW)
2167 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2168 pdmUnlock(pVM);
2169
2170 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
2171}
2172
2173
2174/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrqNoWait} */
2175static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
2176{
2177 pdmR3DevHlp_PCISetIrq(pDevIns, pPciDev, iIrq, iLevel);
2178}
2179
2180
2181/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrq} */
2182static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
2183{
2184 PDMDEV_ASSERT_DEVINS(pDevIns);
2185 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
2186
2187 /*
2188 * Validate input.
2189 */
2190 Assert(iIrq < 16);
2191 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
2192
2193 PVM pVM = pDevIns->Internal.s.pVMR3;
2194
2195 /*
2196 * Do the job.
2197 */
2198 pdmLock(pVM);
2199 uint32_t uTagSrc;
2200 if (iLevel & PDM_IRQ_LEVEL_HIGH)
2201 {
2202 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
2203 if (iLevel == PDM_IRQ_LEVEL_HIGH)
2204 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2205 else
2206 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2207 }
2208 else
2209 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
2210
2211 PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */
2212
2213 if (iLevel == PDM_IRQ_LEVEL_LOW)
2214 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2215 pdmUnlock(pVM);
2216
2217 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
2218}
2219
2220
2221/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrqNoWait} */
2222static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
2223{
2224 pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
2225}
2226
2227
2228/** @interface_method_impl{PDMDEVHLPR3,pfnIoApicSendMsi} */
2229static DECLCALLBACK(void) pdmR3DevHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue)
2230{
2231 PDMDEV_ASSERT_DEVINS(pDevIns);
2232 LogFlow(("pdmR3DevHlp_IoApicSendMsi: caller='%s'/%d: GCPhys=%RGp uValue=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, uValue));
2233
2234 /*
2235 * Validate input.
2236 */
2237 Assert(GCPhys != 0);
2238 Assert(uValue != 0);
2239
2240 PVM pVM = pDevIns->Internal.s.pVMR3;
2241
2242 /*
2243 * Do the job.
2244 */
2245 pdmLock(pVM);
2246 uint32_t uTagSrc;
2247 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
2248 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2249
2250 PDMIoApicSendMsi(pVM, GCPhys, uValue, uTagSrc); /* (The API takes the lock recursively.) */
2251
2252 pdmUnlock(pVM);
2253
2254 LogFlow(("pdmR3DevHlp_IoApicSendMsi: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
2255}
2256
2257
2258/** @interface_method_impl{PDMDEVHLPR3,pfnDriverAttach} */
2259static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
2260{
2261 PDMDEV_ASSERT_DEVINS(pDevIns);
2262 PVM pVM = pDevIns->Internal.s.pVMR3;
2263 VM_ASSERT_EMT(pVM);
2264 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
2265 pDevIns->pReg->szName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
2266
2267 /*
2268 * Lookup the LUN, it might already be registered.
2269 */
2270 PPDMLUN pLunPrev = NULL;
2271 PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;
2272 for (; pLun; pLunPrev = pLun, pLun = pLun->pNext)
2273 if (pLun->iLun == iLun)
2274 break;
2275
2276 /*
2277 * Create the LUN if if wasn't found, else check if driver is already attached to it.
2278 */
2279 if (!pLun)
2280 {
2281 if ( !pBaseInterface
2282 || !pszDesc
2283 || !*pszDesc)
2284 {
2285 Assert(pBaseInterface);
2286 Assert(pszDesc || *pszDesc);
2287 return VERR_INVALID_PARAMETER;
2288 }
2289
2290 pLun = (PPDMLUN)MMR3HeapAlloc(pVM, MM_TAG_PDM_LUN, sizeof(*pLun));
2291 if (!pLun)
2292 return VERR_NO_MEMORY;
2293
2294 pLun->iLun = iLun;
2295 pLun->pNext = pLunPrev ? pLunPrev->pNext : NULL;
2296 pLun->pTop = NULL;
2297 pLun->pBottom = NULL;
2298 pLun->pDevIns = pDevIns;
2299 pLun->pUsbIns = NULL;
2300 pLun->pszDesc = pszDesc;
2301 pLun->pBase = pBaseInterface;
2302 if (!pLunPrev)
2303 pDevIns->Internal.s.pLunsR3 = pLun;
2304 else
2305 pLunPrev->pNext = pLun;
2306 Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
2307 iLun, pszDesc, pDevIns->pReg->szName, pDevIns->iInstance));
2308 }
2309 else if (pLun->pTop)
2310 {
2311 AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
2312 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
2313 return VERR_PDM_DRIVER_ALREADY_ATTACHED;
2314 }
2315 Assert(pLun->pBase == pBaseInterface);
2316
2317
2318 /*
2319 * Get the attached driver configuration.
2320 */
2321 int rc;
2322 PCFGMNODE pNode = CFGMR3GetChildF(pDevIns->Internal.s.pCfgHandle, "LUN#%u", iLun);
2323 if (pNode)
2324 rc = pdmR3DrvInstantiate(pVM, pNode, pBaseInterface, NULL /*pDrvAbove*/, pLun, ppBaseInterface);
2325 else
2326 rc = VERR_PDM_NO_ATTACHED_DRIVER;
2327
2328 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2329 return rc;
2330}
2331
2332
2333/** @interface_method_impl{PDMDEVHLPR3,pfnDriverDetach} */
2334static DECLCALLBACK(int) pdmR3DevHlp_DriverDetach(PPDMDEVINS pDevIns, PPDMDRVINS pDrvIns, uint32_t fFlags)
2335{
2336 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
2337 LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: pDrvIns=%p\n",
2338 pDevIns->pReg->szName, pDevIns->iInstance, pDrvIns));
2339
2340#ifdef VBOX_STRICT
2341 PVM pVM = pDevIns->Internal.s.pVMR3;
2342 VM_ASSERT_EMT(pVM);
2343#endif
2344
2345 int rc = pdmR3DrvDetach(pDrvIns, fFlags);
2346
2347 LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2348 return rc;
2349}
2350
2351
2352/** @interface_method_impl{PDMDEVHLPR3,pfnQueueCreate} */
2353static DECLCALLBACK(int) pdmR3DevHlp_QueueCreate(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
2354 PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue)
2355{
2356 PDMDEV_ASSERT_DEVINS(pDevIns);
2357 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fRZEnabled=%RTbool pszName=%p:{%s} ppQueue=%p\n",
2358 pDevIns->pReg->szName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, pszName, ppQueue));
2359
2360 PVM pVM = pDevIns->Internal.s.pVMR3;
2361 VM_ASSERT_EMT(pVM);
2362
2363 if (pDevIns->iInstance > 0)
2364 {
2365 pszName = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s_%u", pszName, pDevIns->iInstance);
2366 AssertLogRelReturn(pszName, VERR_NO_MEMORY);
2367 }
2368
2369 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, ppQueue);
2370
2371 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *ppQueue));
2372 return rc;
2373}
2374
2375
2376/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectInit} */
2377static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
2378 const char *pszNameFmt, va_list va)
2379{
2380 PDMDEV_ASSERT_DEVINS(pDevIns);
2381 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszNameFmt=%p:{%s}\n",
2382 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pszNameFmt, pszNameFmt));
2383
2384 PVM pVM = pDevIns->Internal.s.pVMR3;
2385 VM_ASSERT_EMT(pVM);
2386 int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
2387
2388 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2389 return rc;
2390}
2391
2392
2393/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNop} */
2394static DECLCALLBACK(PPDMCRITSECT) pdmR3DevHlp_CritSectGetNop(PPDMDEVINS pDevIns)
2395{
2396 PDMDEV_ASSERT_DEVINS(pDevIns);
2397 PVM pVM = pDevIns->Internal.s.pVMR3;
2398 VM_ASSERT_EMT(pVM);
2399
2400 PPDMCRITSECT pCritSect = PDMR3CritSectGetNop(pVM);
2401 LogFlow(("pdmR3DevHlp_CritSectGetNop: caller='%s'/%d: return %p\n",
2402 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2403 return pCritSect;
2404}
2405
2406
2407/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopR0} */
2408static DECLCALLBACK(R0PTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopR0(PPDMDEVINS pDevIns)
2409{
2410 PDMDEV_ASSERT_DEVINS(pDevIns);
2411 PVM pVM = pDevIns->Internal.s.pVMR3;
2412 VM_ASSERT_EMT(pVM);
2413
2414 R0PTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopR0(pVM);
2415 LogFlow(("pdmR3DevHlp_CritSectGetNopR0: caller='%s'/%d: return %RHv\n",
2416 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2417 return pCritSect;
2418}
2419
2420
2421/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopRC} */
2422static DECLCALLBACK(RCPTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopRC(PPDMDEVINS pDevIns)
2423{
2424 PDMDEV_ASSERT_DEVINS(pDevIns);
2425 PVM pVM = pDevIns->Internal.s.pVMR3;
2426 VM_ASSERT_EMT(pVM);
2427
2428 RCPTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopRC(pVM);
2429 LogFlow(("pdmR3DevHlp_CritSectGetNopRC: caller='%s'/%d: return %RRv\n",
2430 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2431 return pCritSect;
2432}
2433
2434
2435/** @interface_method_impl{PDMDEVHLPR3,pfnSetDeviceCritSect} */
2436static DECLCALLBACK(int) pdmR3DevHlp_SetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2437{
2438 /*
2439 * Validate input.
2440 *
2441 * Note! We only allow the automatically created default critical section
2442 * to be replaced by this API.
2443 */
2444 PDMDEV_ASSERT_DEVINS(pDevIns);
2445 AssertPtrReturn(pCritSect, VERR_INVALID_POINTER);
2446 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: pCritSect=%p (%s)\n",
2447 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pCritSect->s.pszName));
2448 AssertReturn(PDMCritSectIsInitialized(pCritSect), VERR_INVALID_PARAMETER);
2449 PVM pVM = pDevIns->Internal.s.pVMR3;
2450 AssertReturn(pCritSect->s.pVMR3 == pVM, VERR_INVALID_PARAMETER);
2451
2452 VM_ASSERT_EMT(pVM);
2453 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
2454
2455 AssertReturn(pDevIns->pCritSectRoR3, VERR_PDM_DEV_IPE_1);
2456 AssertReturn(pDevIns->pCritSectRoR3->s.fAutomaticDefaultCritsect, VERR_WRONG_ORDER);
2457 AssertReturn(!pDevIns->pCritSectRoR3->s.fUsedByTimerOrSimilar, VERR_WRONG_ORDER);
2458 AssertReturn(pDevIns->pCritSectRoR3 != pCritSect, VERR_INVALID_PARAMETER);
2459
2460 /*
2461 * Replace the critical section and destroy the automatic default section.
2462 */
2463 PPDMCRITSECT pOldCritSect = pDevIns->pCritSectRoR3;
2464 pDevIns->pCritSectRoR3 = pCritSect;
2465 pDevIns->Internal.s.fIntFlags |= PDMDEVINSINT_FLAGS_CHANGED_CRITSECT;
2466
2467 Assert(RT_BOOL(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED) == pDevIns->fR0Enabled);
2468 if ( (pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED)
2469 && !(pDevIns->Internal.s.pDevR3->pReg->fFlags & PDM_DEVREG_FLAGS_NEW_STYLE))
2470 {
2471 PDMDEVICECOMPATSETCRITSECTREQ Req;
2472 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
2473 Req.Hdr.cbReq = sizeof(Req);
2474 Req.idxR0Device = pDevIns->Internal.s.idxR0Device;
2475 Req.pDevInsR3 = pDevIns;
2476 Req.pCritSectR3 = pCritSect;
2477 int rc = VMMR3CallR0(pVM, VMMR0_DO_PDM_DEVICE_COMPAT_SET_CRITSECT, 0, &Req.Hdr);
2478 AssertLogRelRCReturn(rc, rc);
2479 }
2480
2481 PDMR3CritSectDelete(pOldCritSect);
2482 Assert((uintptr_t)pOldCritSect - (uintptr_t)pDevIns < pDevIns->cbRing3);
2483
2484 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
2485 return VINF_SUCCESS;
2486}
2487
2488
2489/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectYield} */
2490static DECLCALLBACK(bool) pdmR3DevHlp_CritSectYield(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2491{
2492 PDMDEV_ASSERT_DEVINS(pDevIns);
2493 return PDMR3CritSectYield(pDevIns->Internal.s.pVMR3, pCritSect);
2494}
2495
2496
2497/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnter} */
2498static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy)
2499{
2500 PDMDEV_ASSERT_DEVINS(pDevIns);
2501 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2502 return PDMCritSectEnter(pCritSect, rcBusy);
2503}
2504
2505
2506/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnterDebug} */
2507static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
2508{
2509 PDMDEV_ASSERT_DEVINS(pDevIns);
2510 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2511 return PDMCritSectEnterDebug(pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
2512}
2513
2514
2515/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnter} */
2516static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2517{
2518 PDMDEV_ASSERT_DEVINS(pDevIns);
2519 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2520 return PDMCritSectTryEnter(pCritSect);
2521}
2522
2523
2524/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnterDebug} */
2525static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
2526{
2527 PDMDEV_ASSERT_DEVINS(pDevIns);
2528 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2529 return PDMCritSectTryEnterDebug(pCritSect, uId, RT_SRC_POS_ARGS);
2530}
2531
2532
2533/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectLeave} */
2534static DECLCALLBACK(int) pdmR3DevHlp_CritSectLeave(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2535{
2536 PDMDEV_ASSERT_DEVINS(pDevIns);
2537 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2538 return PDMCritSectLeave(pCritSect);
2539}
2540
2541
2542/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsOwner} */
2543static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsOwner(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2544{
2545 PDMDEV_ASSERT_DEVINS(pDevIns);
2546 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2547 return PDMCritSectIsOwner(pCritSect);
2548}
2549
2550
2551/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsInitialized} */
2552static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsInitialized(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2553{
2554 PDMDEV_ASSERT_DEVINS(pDevIns);
2555 RT_NOREF(pDevIns);
2556 return PDMCritSectIsInitialized(pCritSect);
2557}
2558
2559
2560/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectHasWaiters} */
2561static DECLCALLBACK(bool) pdmR3DevHlp_CritSectHasWaiters(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2562{
2563 PDMDEV_ASSERT_DEVINS(pDevIns);
2564 RT_NOREF(pDevIns);
2565 return PDMCritSectHasWaiters(pCritSect);
2566}
2567
2568
2569/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetRecursion} */
2570static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectGetRecursion(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2571{
2572 PDMDEV_ASSERT_DEVINS(pDevIns);
2573 RT_NOREF(pDevIns);
2574 return PDMCritSectGetRecursion(pCritSect);
2575}
2576
2577
2578/** @interface_method_impl{PDMDEVHLPR3,pfnThreadCreate} */
2579static DECLCALLBACK(int) pdmR3DevHlp_ThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
2580 PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
2581{
2582 PDMDEV_ASSERT_DEVINS(pDevIns);
2583 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2584 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
2585 pDevIns->pReg->szName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
2586
2587 int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
2588
2589 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDevIns->pReg->szName, pDevIns->iInstance,
2590 rc, *ppThread));
2591 return rc;
2592}
2593
2594
2595/** @interface_method_impl{PDMDEVHLPR3,pfnSetAsyncNotification} */
2596static DECLCALLBACK(int) pdmR3DevHlp_SetAsyncNotification(PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)
2597{
2598 PDMDEV_ASSERT_DEVINS(pDevIns);
2599 VM_ASSERT_EMT0(pDevIns->Internal.s.pVMR3);
2600 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: pfnAsyncNotify=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pfnAsyncNotify));
2601
2602 int rc = VINF_SUCCESS;
2603 AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
2604 AssertStmt(!pDevIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
2605 AssertStmt(pDevIns->Internal.s.fIntFlags & (PDMDEVINSINT_FLAGS_SUSPENDED | PDMDEVINSINT_FLAGS_RESET), rc = VERR_WRONG_ORDER);
2606 VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
2607 AssertStmt( enmVMState == VMSTATE_SUSPENDING
2608 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
2609 || enmVMState == VMSTATE_SUSPENDING_LS
2610 || enmVMState == VMSTATE_RESETTING
2611 || enmVMState == VMSTATE_RESETTING_LS
2612 || enmVMState == VMSTATE_POWERING_OFF
2613 || enmVMState == VMSTATE_POWERING_OFF_LS,
2614 rc = VERR_INVALID_STATE);
2615
2616 if (RT_SUCCESS(rc))
2617 pDevIns->Internal.s.pfnAsyncNotify = pfnAsyncNotify;
2618
2619 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2620 return rc;
2621}
2622
2623
2624/** @interface_method_impl{PDMDEVHLPR3,pfnAsyncNotificationCompleted} */
2625static DECLCALLBACK(void) pdmR3DevHlp_AsyncNotificationCompleted(PPDMDEVINS pDevIns)
2626{
2627 PDMDEV_ASSERT_DEVINS(pDevIns);
2628 PVM pVM = pDevIns->Internal.s.pVMR3;
2629
2630 VMSTATE enmVMState = VMR3GetState(pVM);
2631 if ( enmVMState == VMSTATE_SUSPENDING
2632 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
2633 || enmVMState == VMSTATE_SUSPENDING_LS
2634 || enmVMState == VMSTATE_RESETTING
2635 || enmVMState == VMSTATE_RESETTING_LS
2636 || enmVMState == VMSTATE_POWERING_OFF
2637 || enmVMState == VMSTATE_POWERING_OFF_LS)
2638 {
2639 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2640 VMR3AsyncPdmNotificationWakeupU(pVM->pUVM);
2641 }
2642 else
2643 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d: enmVMState=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, enmVMState));
2644}
2645
2646
2647/** @interface_method_impl{PDMDEVHLPR3,pfnRTCRegister} */
2648static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
2649{
2650 PDMDEV_ASSERT_DEVINS(pDevIns);
2651 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2652 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
2653 pDevIns->pReg->szName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
2654 pRtcReg->pfnWrite, ppRtcHlp));
2655
2656 /*
2657 * Validate input.
2658 */
2659 if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
2660 {
2661 AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
2662 PDM_RTCREG_VERSION));
2663 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (version)\n",
2664 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2665 return VERR_INVALID_PARAMETER;
2666 }
2667 if ( !pRtcReg->pfnWrite
2668 || !pRtcReg->pfnRead)
2669 {
2670 Assert(pRtcReg->pfnWrite);
2671 Assert(pRtcReg->pfnRead);
2672 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
2673 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2674 return VERR_INVALID_PARAMETER;
2675 }
2676
2677 if (!ppRtcHlp)
2678 {
2679 Assert(ppRtcHlp);
2680 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (ppRtcHlp)\n",
2681 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2682 return VERR_INVALID_PARAMETER;
2683 }
2684
2685 /*
2686 * Only one DMA device.
2687 */
2688 PVM pVM = pDevIns->Internal.s.pVMR3;
2689 if (pVM->pdm.s.pRtc)
2690 {
2691 AssertMsgFailed(("Only one RTC device is supported!\n"));
2692 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
2693 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2694 return VERR_INVALID_PARAMETER;
2695 }
2696
2697 /*
2698 * Allocate and initialize pci bus structure.
2699 */
2700 int rc = VINF_SUCCESS;
2701 PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
2702 if (pRtc)
2703 {
2704 pRtc->pDevIns = pDevIns;
2705 pRtc->Reg = *pRtcReg;
2706 pVM->pdm.s.pRtc = pRtc;
2707
2708 /* set the helper pointer. */
2709 *ppRtcHlp = &g_pdmR3DevRtcHlp;
2710 Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
2711 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
2712 }
2713 else
2714 rc = VERR_NO_MEMORY;
2715
2716 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
2717 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2718 return rc;
2719}
2720
2721
2722/** @interface_method_impl{PDMDEVHLPR3,pfnDMARegister} */
2723static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
2724{
2725 PDMDEV_ASSERT_DEVINS(pDevIns);
2726 PVM pVM = pDevIns->Internal.s.pVMR3;
2727 VM_ASSERT_EMT(pVM);
2728 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
2729 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
2730 int rc = VINF_SUCCESS;
2731 if (pVM->pdm.s.pDmac)
2732 pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
2733 else
2734 {
2735 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2736 rc = VERR_PDM_NO_DMAC_INSTANCE;
2737 }
2738 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Rrc\n",
2739 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2740 return rc;
2741}
2742
2743
2744/** @interface_method_impl{PDMDEVHLPR3,pfnDMAReadMemory} */
2745static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
2746{
2747 PDMDEV_ASSERT_DEVINS(pDevIns);
2748 PVM pVM = pDevIns->Internal.s.pVMR3;
2749 VM_ASSERT_EMT(pVM);
2750 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
2751 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
2752 int rc = VINF_SUCCESS;
2753 if (pVM->pdm.s.pDmac)
2754 {
2755 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
2756 if (pcbRead)
2757 *pcbRead = cb;
2758 }
2759 else
2760 {
2761 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2762 rc = VERR_PDM_NO_DMAC_INSTANCE;
2763 }
2764 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Rrc\n",
2765 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2766 return rc;
2767}
2768
2769
2770/** @interface_method_impl{PDMDEVHLPR3,pfnDMAWriteMemory} */
2771static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
2772{
2773 PDMDEV_ASSERT_DEVINS(pDevIns);
2774 PVM pVM = pDevIns->Internal.s.pVMR3;
2775 VM_ASSERT_EMT(pVM);
2776 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
2777 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
2778 int rc = VINF_SUCCESS;
2779 if (pVM->pdm.s.pDmac)
2780 {
2781 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
2782 if (pcbWritten)
2783 *pcbWritten = cb;
2784 }
2785 else
2786 {
2787 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2788 rc = VERR_PDM_NO_DMAC_INSTANCE;
2789 }
2790 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Rrc\n",
2791 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2792 return rc;
2793}
2794
2795
2796/** @interface_method_impl{PDMDEVHLPR3,pfnDMASetDREQ} */
2797static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
2798{
2799 PDMDEV_ASSERT_DEVINS(pDevIns);
2800 PVM pVM = pDevIns->Internal.s.pVMR3;
2801 VM_ASSERT_EMT(pVM);
2802 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
2803 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, uLevel));
2804 int rc = VINF_SUCCESS;
2805 if (pVM->pdm.s.pDmac)
2806 pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
2807 else
2808 {
2809 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2810 rc = VERR_PDM_NO_DMAC_INSTANCE;
2811 }
2812 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Rrc\n",
2813 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2814 return rc;
2815}
2816
2817/** @interface_method_impl{PDMDEVHLPR3,pfnDMAGetChannelMode} */
2818static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
2819{
2820 PDMDEV_ASSERT_DEVINS(pDevIns);
2821 PVM pVM = pDevIns->Internal.s.pVMR3;
2822 VM_ASSERT_EMT(pVM);
2823 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
2824 pDevIns->pReg->szName, pDevIns->iInstance, uChannel));
2825 uint8_t u8Mode;
2826 if (pVM->pdm.s.pDmac)
2827 u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
2828 else
2829 {
2830 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2831 u8Mode = 3 << 2 /* illegal mode type */;
2832 }
2833 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
2834 pDevIns->pReg->szName, pDevIns->iInstance, u8Mode));
2835 return u8Mode;
2836}
2837
2838/** @interface_method_impl{PDMDEVHLPR3,pfnDMASchedule} */
2839static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
2840{
2841 PDMDEV_ASSERT_DEVINS(pDevIns);
2842 PVM pVM = pDevIns->Internal.s.pVMR3;
2843 VM_ASSERT_EMT(pVM);
2844 LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
2845 pDevIns->pReg->szName, pDevIns->iInstance, VM_FF_IS_SET(pVM, VM_FF_PDM_DMA)));
2846
2847 AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2848 VM_FF_SET(pVM, VM_FF_PDM_DMA);
2849#ifdef VBOX_WITH_REM
2850 REMR3NotifyDmaPending(pVM);
2851#endif
2852 VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
2853}
2854
2855
2856/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSWrite} */
2857static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
2858{
2859 PDMDEV_ASSERT_DEVINS(pDevIns);
2860 PVM pVM = pDevIns->Internal.s.pVMR3;
2861 VM_ASSERT_EMT(pVM);
2862
2863 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
2864 pDevIns->pReg->szName, pDevIns->iInstance, iReg, u8Value));
2865 int rc;
2866 if (pVM->pdm.s.pRtc)
2867 {
2868 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
2869 rc = PDMCritSectEnter(pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
2870 if (RT_SUCCESS(rc))
2871 {
2872 rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pDevInsRtc, iReg, u8Value);
2873 PDMCritSectLeave(pDevInsRtc->pCritSectRoR3);
2874 }
2875 }
2876 else
2877 rc = VERR_PDM_NO_RTC_INSTANCE;
2878
2879 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
2880 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2881 return rc;
2882}
2883
2884
2885/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSRead} */
2886static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
2887{
2888 PDMDEV_ASSERT_DEVINS(pDevIns);
2889 PVM pVM = pDevIns->Internal.s.pVMR3;
2890 VM_ASSERT_EMT(pVM);
2891
2892 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
2893 pDevIns->pReg->szName, pDevIns->iInstance, iReg, pu8Value));
2894 int rc;
2895 if (pVM->pdm.s.pRtc)
2896 {
2897 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
2898 rc = PDMCritSectEnter(pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
2899 if (RT_SUCCESS(rc))
2900 {
2901 rc = pVM->pdm.s.pRtc->Reg.pfnRead(pDevInsRtc, iReg, pu8Value);
2902 PDMCritSectLeave(pDevInsRtc->pCritSectRoR3);
2903 }
2904 }
2905 else
2906 rc = VERR_PDM_NO_RTC_INSTANCE;
2907
2908 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
2909 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2910 return rc;
2911}
2912
2913
2914/** @interface_method_impl{PDMDEVHLPR3,pfnAssertEMT} */
2915static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
2916{
2917 PDMDEV_ASSERT_DEVINS(pDevIns);
2918 if (VM_IS_EMT(pDevIns->Internal.s.pVMR3))
2919 return true;
2920
2921 char szMsg[100];
2922 RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
2923 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
2924 AssertBreakpoint();
2925 return false;
2926}
2927
2928
2929/** @interface_method_impl{PDMDEVHLPR3,pfnAssertOther} */
2930static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
2931{
2932 PDMDEV_ASSERT_DEVINS(pDevIns);
2933 if (!VM_IS_EMT(pDevIns->Internal.s.pVMR3))
2934 return true;
2935
2936 char szMsg[100];
2937 RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
2938 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
2939 AssertBreakpoint();
2940 return false;
2941}
2942
2943
2944/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetRCInterfaceSymbols} */
2945static DECLCALLBACK(int) pdmR3DevHlp_LdrGetRCInterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
2946 const char *pszSymPrefix, const char *pszSymList)
2947{
2948 PDMDEV_ASSERT_DEVINS(pDevIns);
2949 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2950 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
2951 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
2952
2953 int rc;
2954 if ( strncmp(pszSymPrefix, "dev", 3) == 0
2955 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
2956 {
2957 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
2958 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
2959 pvInterface, cbInterface,
2960 pDevIns->pReg->pszRCMod, pDevIns->Internal.s.pDevR3->pszRCSearchPath,
2961 pszSymPrefix, pszSymList,
2962 false /*fRing0OrRC*/);
2963 else
2964 {
2965 AssertMsgFailed(("Not a raw-mode enabled driver\n"));
2966 rc = VERR_PERMISSION_DENIED;
2967 }
2968 }
2969 else
2970 {
2971 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
2972 pszSymPrefix, pDevIns->pReg->szName));
2973 rc = VERR_INVALID_NAME;
2974 }
2975
2976 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
2977 pDevIns->iInstance, rc));
2978 return rc;
2979}
2980
2981
2982/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetR0InterfaceSymbols} */
2983static DECLCALLBACK(int) pdmR3DevHlp_LdrGetR0InterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
2984 const char *pszSymPrefix, const char *pszSymList)
2985{
2986 PDMDEV_ASSERT_DEVINS(pDevIns);
2987 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2988 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
2989 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
2990
2991 int rc;
2992 if ( strncmp(pszSymPrefix, "dev", 3) == 0
2993 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
2994 {
2995 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
2996 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
2997 pvInterface, cbInterface,
2998 pDevIns->pReg->pszR0Mod, pDevIns->Internal.s.pDevR3->pszR0SearchPath,
2999 pszSymPrefix, pszSymList,
3000 true /*fRing0OrRC*/);
3001 else
3002 {
3003 AssertMsgFailed(("Not a ring-0 enabled driver\n"));
3004 rc = VERR_PERMISSION_DENIED;
3005 }
3006 }
3007 else
3008 {
3009 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
3010 pszSymPrefix, pDevIns->pReg->szName));
3011 rc = VERR_INVALID_NAME;
3012 }
3013
3014 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3015 pDevIns->iInstance, rc));
3016 return rc;
3017}
3018
3019
3020/** @interface_method_impl{PDMDEVHLPR3,pfnCallR0} */
3021static DECLCALLBACK(int) pdmR3DevHlp_CallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
3022{
3023 PDMDEV_ASSERT_DEVINS(pDevIns);
3024 PVM pVM = pDevIns->Internal.s.pVMR3;
3025 VM_ASSERT_EMT(pVM);
3026 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: uOperation=%#x u64Arg=%#RX64\n",
3027 pDevIns->pReg->szName, pDevIns->iInstance, uOperation, u64Arg));
3028
3029 /*
3030 * Resolve the ring-0 entry point. There is not need to remember this like
3031 * we do for drivers since this is mainly for construction time hacks and
3032 * other things that aren't performance critical.
3033 */
3034 int rc;
3035 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3036 {
3037 char szSymbol[ sizeof("devR0") + sizeof(pDevIns->pReg->szName) + sizeof("ReqHandler")];
3038 strcat(strcat(strcpy(szSymbol, "devR0"), pDevIns->pReg->szName), "ReqHandler");
3039 szSymbol[sizeof("devR0") - 1] = RT_C_TO_UPPER(szSymbol[sizeof("devR0") - 1]);
3040
3041 PFNPDMDRVREQHANDLERR0 pfnReqHandlerR0;
3042 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, szSymbol, &pfnReqHandlerR0);
3043 if (RT_SUCCESS(rc))
3044 {
3045 /*
3046 * Make the ring-0 call.
3047 */
3048 PDMDEVICECALLREQHANDLERREQ Req;
3049 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
3050 Req.Hdr.cbReq = sizeof(Req);
3051 Req.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3052 Req.pfnReqHandlerR0 = pfnReqHandlerR0;
3053 Req.uOperation = uOperation;
3054 Req.u32Alignment = 0;
3055 Req.u64Arg = u64Arg;
3056 rc = SUPR3CallVMMR0Ex(VMCC_GET_VMR0_FOR_CALL(pVM), NIL_VMCPUID, VMMR0_DO_PDM_DEVICE_CALL_REQ_HANDLER, 0, &Req.Hdr);
3057 }
3058 else
3059 pfnReqHandlerR0 = NIL_RTR0PTR;
3060 }
3061 else
3062 rc = VERR_ACCESS_DENIED;
3063 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3064 pDevIns->iInstance, rc));
3065 return rc;
3066}
3067
3068
3069/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetSuspendReason} */
3070static DECLCALLBACK(VMSUSPENDREASON) pdmR3DevHlp_VMGetSuspendReason(PPDMDEVINS pDevIns)
3071{
3072 PDMDEV_ASSERT_DEVINS(pDevIns);
3073 PVM pVM = pDevIns->Internal.s.pVMR3;
3074 VM_ASSERT_EMT(pVM);
3075 VMSUSPENDREASON enmReason = VMR3GetSuspendReason(pVM->pUVM);
3076 LogFlow(("pdmR3DevHlp_VMGetSuspendReason: caller='%s'/%d: returns %d\n",
3077 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3078 return enmReason;
3079}
3080
3081
3082/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetResumeReason} */
3083static DECLCALLBACK(VMRESUMEREASON) pdmR3DevHlp_VMGetResumeReason(PPDMDEVINS pDevIns)
3084{
3085 PDMDEV_ASSERT_DEVINS(pDevIns);
3086 PVM pVM = pDevIns->Internal.s.pVMR3;
3087 VM_ASSERT_EMT(pVM);
3088 VMRESUMEREASON enmReason = VMR3GetResumeReason(pVM->pUVM);
3089 LogFlow(("pdmR3DevHlp_VMGetResumeReason: caller='%s'/%d: returns %d\n",
3090 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3091 return enmReason;
3092}
3093
3094
3095/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
3096static DECLCALLBACK(PUVM) pdmR3DevHlp_GetUVM(PPDMDEVINS pDevIns)
3097{
3098 PDMDEV_ASSERT_DEVINS(pDevIns);
3099 LogFlow(("pdmR3DevHlp_GetUVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3100 return pDevIns->Internal.s.pVMR3->pUVM;
3101}
3102
3103
3104/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
3105static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
3106{
3107 PDMDEV_ASSERT_DEVINS(pDevIns);
3108 LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3109 return pDevIns->Internal.s.pVMR3;
3110}
3111
3112
3113/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
3114static DECLCALLBACK(PVMCPU) pdmR3DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
3115{
3116 PDMDEV_ASSERT_DEVINS(pDevIns);
3117 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3118 LogFlow(("pdmR3DevHlp_GetVMCPU: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, VMMGetCpuId(pDevIns->Internal.s.pVMR3)));
3119 return VMMGetCpu(pDevIns->Internal.s.pVMR3);
3120}
3121
3122
3123/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
3124static DECLCALLBACK(VMCPUID) pdmR3DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
3125{
3126 PDMDEV_ASSERT_DEVINS(pDevIns);
3127 VMCPUID idCpu = VMMGetCpuId(pDevIns->Internal.s.pVMR3);
3128 LogFlow(("pdmR3DevHlp_GetCurrentCpuId: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, idCpu));
3129 return idCpu;
3130}
3131
3132
3133/** @interface_method_impl{PDMDEVHLPR3,pfnPCIBusRegister} */
3134static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg,
3135 PCPDMPCIHLPR3 *ppPciHlpR3, uint32_t *piBus)
3136{
3137 PDMDEV_ASSERT_DEVINS(pDevIns);
3138 PVM pVM = pDevIns->Internal.s.pVMR3;
3139 VM_ASSERT_EMT(pVM);
3140 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, "
3141 ".pfnSetIrqR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppPciHlpR3=%p piBus=%p\n",
3142 pDevIns->pReg->szName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
3143 pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnSetIrqR3, pPciBusReg->pszSetIrqRC, pPciBusReg->pszSetIrqRC,
3144 pPciBusReg->pszSetIrqR0, pPciBusReg->pszSetIrqR0, ppPciHlpR3, piBus));
3145
3146 /*
3147 * Validate the structure.
3148 */
3149 if (pPciBusReg->u32Version != PDM_PCIBUSREG_VERSION)
3150 {
3151 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREG_VERSION));
3152 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3153 return VERR_INVALID_PARAMETER;
3154 }
3155 if ( !pPciBusReg->pfnRegisterR3
3156 || !pPciBusReg->pfnIORegionRegisterR3
3157 || !pPciBusReg->pfnSetIrqR3)
3158 {
3159 Assert(pPciBusReg->pfnRegisterR3);
3160 Assert(pPciBusReg->pfnIORegionRegisterR3);
3161 Assert(pPciBusReg->pfnSetIrqR3);
3162 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc (R3 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3163 return VERR_INVALID_PARAMETER;
3164 }
3165 if ( pPciBusReg->pszSetIrqRC
3166 && !VALID_PTR(pPciBusReg->pszSetIrqRC))
3167 {
3168 Assert(VALID_PTR(pPciBusReg->pszSetIrqRC));
3169 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3170 return VERR_INVALID_PARAMETER;
3171 }
3172 if ( pPciBusReg->pszSetIrqR0
3173 && !VALID_PTR(pPciBusReg->pszSetIrqR0))
3174 {
3175 Assert(VALID_PTR(pPciBusReg->pszSetIrqR0));
3176 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3177 return VERR_INVALID_PARAMETER;
3178 }
3179 if (!ppPciHlpR3)
3180 {
3181 Assert(ppPciHlpR3);
3182 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc (ppPciHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3183 return VERR_INVALID_PARAMETER;
3184 }
3185 AssertLogRelMsgReturn(RT_VALID_PTR(piBus) || !piBus,
3186 ("caller='%s'/%d: piBus=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, piBus),
3187 VERR_INVALID_POINTER);
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 if (iBus >= RT_ELEMENTS(pVM->pdm.s.aPciBuses))
3197 {
3198 AssertMsgFailed(("Too many PCI buses. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aPciBuses)));
3199 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc (pci bus)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3200 return VERR_INVALID_PARAMETER;
3201 }
3202 PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
3203
3204 /*
3205 * Resolve and init the RC bits.
3206 */
3207 if (pPciBusReg->pszSetIrqRC)
3208 {
3209 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pPciBusReg->pszSetIrqRC, &pPciBus->pfnSetIrqRC);
3210 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pPciBusReg->pszSetIrqRC, rc));
3211 if (RT_FAILURE(rc))
3212 {
3213 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3214 return rc;
3215 }
3216 pPciBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3217 }
3218 else
3219 {
3220 pPciBus->pfnSetIrqRC = 0;
3221 pPciBus->pDevInsRC = 0;
3222 }
3223
3224 /*
3225 * Resolve and init the R0 bits.
3226 */
3227 if (pPciBusReg->pszSetIrqR0)
3228 {
3229 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pPciBusReg->pszSetIrqR0, &pPciBus->pfnSetIrqR0);
3230 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pPciBusReg->pszSetIrqR0, rc));
3231 if (RT_FAILURE(rc))
3232 {
3233 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3234 return rc;
3235 }
3236 pPciBus->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3237 }
3238 else
3239 {
3240 pPciBus->pfnSetIrqR0 = 0;
3241 pPciBus->pDevInsR0 = 0;
3242 }
3243
3244 /*
3245 * Init the R3 bits.
3246 */
3247 pPciBus->iBus = iBus;
3248 pPciBus->pDevInsR3 = pDevIns;
3249 pPciBus->pfnRegisterR3 = pPciBusReg->pfnRegisterR3;
3250 pPciBus->pfnRegisterMsiR3 = pPciBusReg->pfnRegisterMsiR3;
3251 pPciBus->pfnIORegionRegisterR3 = pPciBusReg->pfnIORegionRegisterR3;
3252 pPciBus->pfnSetConfigCallbacksR3 = pPciBusReg->pfnSetConfigCallbacksR3;
3253 pPciBus->pfnSetIrqR3 = pPciBusReg->pfnSetIrqR3;
3254
3255 Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3256
3257 /* set the helper pointer and return. */
3258 *ppPciHlpR3 = &g_pdmR3DevPciHlp;
3259 if (piBus)
3260 *piBus = iBus;
3261 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc *piBus=%u\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS, iBus));
3262 return VINF_SUCCESS;
3263}
3264
3265
3266/** @interface_method_impl{PDMDEVHLPR3,pfnPICRegister} */
3267static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
3268{
3269 PDMDEV_ASSERT_DEVINS(pDevIns);
3270 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3271 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",
3272 pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrqR3, pPicReg->pfnGetInterruptR3,
3273 pPicReg->pszSetIrqRC, pPicReg->pszSetIrqRC, pPicReg->pszGetInterruptRC, pPicReg->pszGetInterruptRC,
3274 pPicReg->pszSetIrqR0, pPicReg->pszSetIrqR0, pPicReg->pszGetInterruptR0, pPicReg->pszGetInterruptR0,
3275 ppPicHlpR3));
3276
3277 /*
3278 * Validate input.
3279 */
3280 if (pPicReg->u32Version != PDM_PICREG_VERSION)
3281 {
3282 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPicReg->u32Version, PDM_PICREG_VERSION));
3283 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3284 return VERR_INVALID_PARAMETER;
3285 }
3286 if ( !pPicReg->pfnSetIrqR3
3287 || !pPicReg->pfnGetInterruptR3)
3288 {
3289 Assert(pPicReg->pfnSetIrqR3);
3290 Assert(pPicReg->pfnGetInterruptR3);
3291 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (R3 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3292 return VERR_INVALID_PARAMETER;
3293 }
3294 if ( ( pPicReg->pszSetIrqRC
3295 || pPicReg->pszGetInterruptRC)
3296 && ( !VALID_PTR(pPicReg->pszSetIrqRC)
3297 || !VALID_PTR(pPicReg->pszGetInterruptRC))
3298 )
3299 {
3300 Assert(VALID_PTR(pPicReg->pszSetIrqRC));
3301 Assert(VALID_PTR(pPicReg->pszGetInterruptRC));
3302 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (RC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3303 return VERR_INVALID_PARAMETER;
3304 }
3305 if ( pPicReg->pszSetIrqRC
3306 && !(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC))
3307 {
3308 Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC);
3309 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (RC flag)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3310 return VERR_INVALID_PARAMETER;
3311 }
3312 if ( pPicReg->pszSetIrqR0
3313 && !(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0))
3314 {
3315 Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0);
3316 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (R0 flag)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3317 return VERR_INVALID_PARAMETER;
3318 }
3319 if (!ppPicHlpR3)
3320 {
3321 Assert(ppPicHlpR3);
3322 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (ppPicHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3323 return VERR_INVALID_PARAMETER;
3324 }
3325
3326 /*
3327 * Only one PIC device.
3328 */
3329 PVM pVM = pDevIns->Internal.s.pVMR3;
3330 if (pVM->pdm.s.Pic.pDevInsR3)
3331 {
3332 AssertMsgFailed(("Only one pic device is supported!\n"));
3333 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3334 return VERR_INVALID_PARAMETER;
3335 }
3336
3337 /*
3338 * RC stuff.
3339 */
3340 if (pPicReg->pszSetIrqRC)
3341 {
3342 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pPicReg->pszSetIrqRC, &pVM->pdm.s.Pic.pfnSetIrqRC);
3343 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pPicReg->pszSetIrqRC, rc));
3344 if (RT_SUCCESS(rc))
3345 {
3346 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pPicReg->pszGetInterruptRC, &pVM->pdm.s.Pic.pfnGetInterruptRC);
3347 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pPicReg->pszGetInterruptRC, rc));
3348 }
3349 if (RT_FAILURE(rc))
3350 {
3351 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3352 return rc;
3353 }
3354 pVM->pdm.s.Pic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3355 }
3356 else
3357 {
3358 pVM->pdm.s.Pic.pDevInsRC = 0;
3359 pVM->pdm.s.Pic.pfnSetIrqRC = 0;
3360 pVM->pdm.s.Pic.pfnGetInterruptRC = 0;
3361 }
3362
3363 /*
3364 * R0 stuff.
3365 */
3366 if (pPicReg->pszSetIrqR0)
3367 {
3368 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pPicReg->pszSetIrqR0, &pVM->pdm.s.Pic.pfnSetIrqR0);
3369 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pPicReg->pszSetIrqR0, rc));
3370 if (RT_SUCCESS(rc))
3371 {
3372 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pPicReg->pszGetInterruptR0, &pVM->pdm.s.Pic.pfnGetInterruptR0);
3373 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pPicReg->pszGetInterruptR0, rc));
3374 }
3375 if (RT_FAILURE(rc))
3376 {
3377 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3378 return rc;
3379 }
3380 pVM->pdm.s.Pic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3381 Assert(pVM->pdm.s.Pic.pDevInsR0);
3382 }
3383 else
3384 {
3385 pVM->pdm.s.Pic.pfnSetIrqR0 = 0;
3386 pVM->pdm.s.Pic.pfnGetInterruptR0 = 0;
3387 pVM->pdm.s.Pic.pDevInsR0 = 0;
3388 }
3389
3390 /*
3391 * R3 stuff.
3392 */
3393 pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
3394 pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrqR3;
3395 pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterruptR3;
3396 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3397
3398 /* set the helper pointer and return. */
3399 *ppPicHlpR3 = &g_pdmR3DevPicHlp;
3400 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3401 return VINF_SUCCESS;
3402}
3403
3404
3405/** @interface_method_impl{PDMDEVHLPR3,pfnAPICRegister} */
3406static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns)
3407{
3408 PDMDEV_ASSERT_DEVINS(pDevIns);
3409 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3410
3411 /*
3412 * Only one APIC device. On SMP we have single logical device covering all LAPICs,
3413 * as they need to communicate and share state easily.
3414 */
3415 PVM pVM = pDevIns->Internal.s.pVMR3;
3416 if (pVM->pdm.s.Apic.pDevInsR3)
3417 {
3418 AssertMsgFailed(("Only one APIC device is supported!\n"));
3419 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3420 return VERR_INVALID_PARAMETER;
3421 }
3422
3423 /*
3424 * Initialize the RC, R0 and HC bits.
3425 */
3426 pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3427 Assert(pVM->pdm.s.Apic.pDevInsRC || !VM_IS_RAW_MODE_ENABLED(pVM));
3428
3429 pVM->pdm.s.Apic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3430 Assert(pVM->pdm.s.Apic.pDevInsR0);
3431
3432 pVM->pdm.s.Apic.pDevInsR3 = pDevIns;
3433 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3434 return VINF_SUCCESS;
3435}
3436
3437
3438/** @interface_method_impl{PDMDEVHLPR3,pfnIOAPICRegister} */
3439static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
3440{
3441 PDMDEV_ASSERT_DEVINS(pDevIns);
3442 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3443 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppIoApicHlpR3=%p\n",
3444 pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqR3,
3445 pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqR0, pIoApicReg->pszSetIrqR0, ppIoApicHlpR3));
3446
3447 /*
3448 * Validate input.
3449 */
3450 if (pIoApicReg->u32Version != PDM_IOAPICREG_VERSION)
3451 {
3452 AssertMsgFailed(("u32Version=%#x expected %#x\n", pIoApicReg->u32Version, PDM_IOAPICREG_VERSION));
3453 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3454 return VERR_INVALID_PARAMETER;
3455 }
3456 if (!pIoApicReg->pfnSetIrqR3 || !pIoApicReg->pfnSendMsiR3 || !pIoApicReg->pfnSetEoiR3)
3457 {
3458 Assert(pIoApicReg->pfnSetIrqR3);
3459 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (R3 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3460 return VERR_INVALID_PARAMETER;
3461 }
3462 if ( pIoApicReg->pszSetIrqRC
3463 && !VALID_PTR(pIoApicReg->pszSetIrqRC))
3464 {
3465 Assert(VALID_PTR(pIoApicReg->pszSetIrqRC));
3466 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3467 return VERR_INVALID_PARAMETER;
3468 }
3469 if ( pIoApicReg->pszSendMsiRC
3470 && !VALID_PTR(pIoApicReg->pszSendMsiRC))
3471 {
3472 Assert(VALID_PTR(pIoApicReg->pszSendMsiRC));
3473 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3474 return VERR_INVALID_PARAMETER;
3475 }
3476 if ( pIoApicReg->pszSetEoiRC
3477 && !VALID_PTR(pIoApicReg->pszSetEoiRC))
3478 {
3479 Assert(VALID_PTR(pIoApicReg->pszSetEoiRC));
3480 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3481 return VERR_INVALID_PARAMETER;
3482 }
3483 if ( pIoApicReg->pszSetIrqR0
3484 && !VALID_PTR(pIoApicReg->pszSetIrqR0))
3485 {
3486 Assert(VALID_PTR(pIoApicReg->pszSetIrqR0));
3487 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3488 return VERR_INVALID_PARAMETER;
3489 }
3490 if ( pIoApicReg->pszSendMsiR0
3491 && !VALID_PTR(pIoApicReg->pszSendMsiR0))
3492 {
3493 Assert(VALID_PTR(pIoApicReg->pszSendMsiR0));
3494 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3495 return VERR_INVALID_PARAMETER;
3496 }
3497 if ( pIoApicReg->pszSetEoiR0
3498 && !VALID_PTR(pIoApicReg->pszSetEoiR0))
3499 {
3500 Assert(VALID_PTR(pIoApicReg->pszSetEoiR0));
3501 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3502 return VERR_INVALID_PARAMETER;
3503 }
3504 if (!ppIoApicHlpR3)
3505 {
3506 Assert(ppIoApicHlpR3);
3507 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (ppApicHlp)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3508 return VERR_INVALID_PARAMETER;
3509 }
3510
3511 /*
3512 * The I/O APIC requires the APIC to be present (hacks++).
3513 * If the I/O APIC does GC stuff so must the APIC.
3514 */
3515 PVM pVM = pDevIns->Internal.s.pVMR3;
3516 if (!pVM->pdm.s.Apic.pDevInsR3)
3517 {
3518 AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
3519 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (no APIC)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3520 return VERR_INVALID_PARAMETER;
3521 }
3522#if 0
3523 if ( pIoApicReg->pszSetIrqRC
3524 && !pVM->pdm.s.Apic.pDevInsRC)
3525 {
3526 AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
3527 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (no GC APIC)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3528 return VERR_INVALID_PARAMETER;
3529 }
3530#endif
3531
3532 /*
3533 * Only one I/O APIC device.
3534 */
3535 if (pVM->pdm.s.IoApic.pDevInsR3)
3536 {
3537 AssertMsgFailed(("Only one ioapic device is supported!\n"));
3538 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (only one)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3539 return VERR_INVALID_PARAMETER;
3540 }
3541
3542 /*
3543 * Resolve & initialize the GC bits.
3544 */
3545 if (pIoApicReg->pszSetIrqRC)
3546 {
3547 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSetIrqRC, &pVM->pdm.s.IoApic.pfnSetIrqRC);
3548 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pIoApicReg->pszSetIrqRC, rc));
3549 if (RT_FAILURE(rc))
3550 {
3551 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3552 return rc;
3553 }
3554 pVM->pdm.s.IoApic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3555 }
3556 else
3557 {
3558 pVM->pdm.s.IoApic.pDevInsRC = 0;
3559 pVM->pdm.s.IoApic.pfnSetIrqRC = 0;
3560 }
3561
3562 if (pIoApicReg->pszSendMsiRC)
3563 {
3564 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSendMsiRC, &pVM->pdm.s.IoApic.pfnSendMsiRC);
3565 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pIoApicReg->pszSendMsiRC, rc));
3566 if (RT_FAILURE(rc))
3567 {
3568 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3569 return rc;
3570 }
3571 }
3572 else
3573 {
3574 pVM->pdm.s.IoApic.pfnSendMsiRC = 0;
3575 }
3576
3577 if (pIoApicReg->pszSetEoiRC)
3578 {
3579 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSetEoiRC, &pVM->pdm.s.IoApic.pfnSetEoiRC);
3580 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pIoApicReg->pszSetEoiRC, rc));
3581 if (RT_FAILURE(rc))
3582 {
3583 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3584 return rc;
3585 }
3586 }
3587 else
3588 {
3589 pVM->pdm.s.IoApic.pfnSetEoiRC = 0;
3590 }
3591
3592 /*
3593 * Resolve & initialize the R0 bits.
3594 */
3595 if (pIoApicReg->pszSetIrqR0)
3596 {
3597 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSetIrqR0);
3598 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pIoApicReg->pszSetIrqR0, rc));
3599 if (RT_FAILURE(rc))
3600 {
3601 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3602 return rc;
3603 }
3604 pVM->pdm.s.IoApic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3605 Assert(pVM->pdm.s.IoApic.pDevInsR0);
3606 }
3607 else
3608 {
3609 pVM->pdm.s.IoApic.pfnSetIrqR0 = 0;
3610 pVM->pdm.s.IoApic.pDevInsR0 = 0;
3611 }
3612
3613 if (pIoApicReg->pszSendMsiR0)
3614 {
3615 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSendMsiR0, &pVM->pdm.s.IoApic.pfnSendMsiR0);
3616 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pIoApicReg->pszSendMsiR0, rc));
3617 if (RT_FAILURE(rc))
3618 {
3619 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3620 return rc;
3621 }
3622 }
3623 else
3624 {
3625 pVM->pdm.s.IoApic.pfnSendMsiR0 = 0;
3626 }
3627
3628 if (pIoApicReg->pszSetEoiR0)
3629 {
3630 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSetEoiR0, &pVM->pdm.s.IoApic.pfnSetEoiR0);
3631 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pIoApicReg->pszSetEoiR0, rc));
3632 if (RT_FAILURE(rc))
3633 {
3634 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3635 return rc;
3636 }
3637 }
3638 else
3639 {
3640 pVM->pdm.s.IoApic.pfnSetEoiR0 = 0;
3641 }
3642
3643
3644 /*
3645 * Initialize the R3 bits.
3646 */
3647 pVM->pdm.s.IoApic.pDevInsR3 = pDevIns;
3648 pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrqR3;
3649 pVM->pdm.s.IoApic.pfnSendMsiR3 = pIoApicReg->pfnSendMsiR3;
3650 pVM->pdm.s.IoApic.pfnSetEoiR3 = pIoApicReg->pfnSetEoiR3;
3651 Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3652
3653 /* set the helper pointer and return. */
3654 *ppIoApicHlpR3 = &g_pdmR3DevIoApicHlp;
3655 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3656 return VINF_SUCCESS;
3657}
3658
3659
3660/** @interface_method_impl{PDMDEVHLPR3,pfnHPETRegister} */
3661static DECLCALLBACK(int) pdmR3DevHlp_HPETRegister(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3)
3662{
3663 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
3664 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3665 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3666
3667 /*
3668 * Validate input.
3669 */
3670 if (pHpetReg->u32Version != PDM_HPETREG_VERSION)
3671 {
3672 AssertMsgFailed(("u32Version=%#x expected %#x\n", pHpetReg->u32Version, PDM_HPETREG_VERSION));
3673 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3674 return VERR_INVALID_PARAMETER;
3675 }
3676
3677 if (!ppHpetHlpR3)
3678 {
3679 Assert(ppHpetHlpR3);
3680 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d: returns %Rrc (ppApicHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3681 return VERR_INVALID_PARAMETER;
3682 }
3683
3684 /* set the helper pointer and return. */
3685 *ppHpetHlpR3 = &g_pdmR3DevHpetHlp;
3686 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3687 return VINF_SUCCESS;
3688}
3689
3690
3691/** @interface_method_impl{PDMDEVHLPR3,pfnPciRawRegister} */
3692static DECLCALLBACK(int) pdmR3DevHlp_PciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
3693{
3694 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
3695 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3696 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3697
3698 /*
3699 * Validate input.
3700 */
3701 if (pPciRawReg->u32Version != PDM_PCIRAWREG_VERSION)
3702 {
3703 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciRawReg->u32Version, PDM_PCIRAWREG_VERSION));
3704 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3705 return VERR_INVALID_PARAMETER;
3706 }
3707
3708 if (!ppPciRawHlpR3)
3709 {
3710 Assert(ppPciRawHlpR3);
3711 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (ppPciRawHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3712 return VERR_INVALID_PARAMETER;
3713 }
3714
3715 /* set the helper pointer and return. */
3716 *ppPciRawHlpR3 = &g_pdmR3DevPciRawHlp;
3717 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3718 return VINF_SUCCESS;
3719}
3720
3721
3722/** @interface_method_impl{PDMDEVHLPR3,pfnDMACRegister} */
3723static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
3724{
3725 PDMDEV_ASSERT_DEVINS(pDevIns);
3726 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3727 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",
3728 pDevIns->pReg->szName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
3729 pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
3730
3731 /*
3732 * Validate input.
3733 */
3734 if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
3735 {
3736 AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
3737 PDM_DMACREG_VERSION));
3738 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (version)\n",
3739 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3740 return VERR_INVALID_PARAMETER;
3741 }
3742 if ( !pDmacReg->pfnRun
3743 || !pDmacReg->pfnRegister
3744 || !pDmacReg->pfnReadMemory
3745 || !pDmacReg->pfnWriteMemory
3746 || !pDmacReg->pfnSetDREQ
3747 || !pDmacReg->pfnGetChannelMode)
3748 {
3749 Assert(pDmacReg->pfnRun);
3750 Assert(pDmacReg->pfnRegister);
3751 Assert(pDmacReg->pfnReadMemory);
3752 Assert(pDmacReg->pfnWriteMemory);
3753 Assert(pDmacReg->pfnSetDREQ);
3754 Assert(pDmacReg->pfnGetChannelMode);
3755 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3756 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3757 return VERR_INVALID_PARAMETER;
3758 }
3759
3760 if (!ppDmacHlp)
3761 {
3762 Assert(ppDmacHlp);
3763 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (ppDmacHlp)\n",
3764 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3765 return VERR_INVALID_PARAMETER;
3766 }
3767
3768 /*
3769 * Only one DMA device.
3770 */
3771 PVM pVM = pDevIns->Internal.s.pVMR3;
3772 if (pVM->pdm.s.pDmac)
3773 {
3774 AssertMsgFailed(("Only one DMA device is supported!\n"));
3775 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3776 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3777 return VERR_INVALID_PARAMETER;
3778 }
3779
3780 /*
3781 * Allocate and initialize pci bus structure.
3782 */
3783 int rc = VINF_SUCCESS;
3784 PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
3785 if (pDmac)
3786 {
3787 pDmac->pDevIns = pDevIns;
3788 pDmac->Reg = *pDmacReg;
3789 pVM->pdm.s.pDmac = pDmac;
3790
3791 /* set the helper pointer. */
3792 *ppDmacHlp = &g_pdmR3DevDmacHlp;
3793 Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
3794 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3795 }
3796 else
3797 rc = VERR_NO_MEMORY;
3798
3799 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3800 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3801 return rc;
3802}
3803
3804
3805/**
3806 * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
3807 */
3808static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbHeap)
3809{
3810 PDMDEV_ASSERT_DEVINS(pDevIns);
3811 PVM pVM = pDevIns->Internal.s.pVMR3;
3812 VM_ASSERT_EMT(pVM);
3813 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: GCPhys=%RGp pvHeap=%p cbHeap=%#x\n",
3814 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvHeap, cbHeap));
3815
3816 if (pVM->pdm.s.pvVMMDevHeap == NULL)
3817 {
3818 pVM->pdm.s.pvVMMDevHeap = pvHeap;
3819 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
3820 pVM->pdm.s.cbVMMDevHeap = cbHeap;
3821 pVM->pdm.s.cbVMMDevHeapLeft = cbHeap;
3822 }
3823 else
3824 {
3825 Assert(pVM->pdm.s.pvVMMDevHeap == pvHeap);
3826 Assert(pVM->pdm.s.cbVMMDevHeap == cbHeap);
3827 Assert(pVM->pdm.s.GCPhysVMMDevHeap != GCPhys || GCPhys == NIL_RTGCPHYS);
3828 if (pVM->pdm.s.GCPhysVMMDevHeap != GCPhys)
3829 {
3830 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
3831 if (pVM->pdm.s.pfnVMMDevHeapNotify)
3832 pVM->pdm.s.pfnVMMDevHeapNotify(pVM, pvHeap, GCPhys);
3833 }
3834 }
3835
3836 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: returns %Rrc\n",
3837 pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3838 return VINF_SUCCESS;
3839}
3840
3841
3842/**
3843 * @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister}
3844 */
3845static DECLCALLBACK(int) pdmR3DevHlp_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
3846{
3847 PDMDEV_ASSERT_DEVINS(pDevIns);
3848 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3849 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: pFWReg=%p:{.u32Version=%#x, .pfnIsHardReset=%p, .u32TheEnd=%#x} ppFwHlp=%p\n",
3850 pDevIns->pReg->szName, pDevIns->iInstance, pFwReg, pFwReg->u32Version, pFwReg->pfnIsHardReset, pFwReg->u32TheEnd, ppFwHlp));
3851
3852 /*
3853 * Validate input.
3854 */
3855 if (pFwReg->u32Version != PDM_FWREG_VERSION)
3856 {
3857 AssertMsgFailed(("u32Version=%#x expected %#x\n", pFwReg->u32Version, PDM_FWREG_VERSION));
3858 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (version)\n",
3859 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3860 return VERR_INVALID_PARAMETER;
3861 }
3862 if (!pFwReg->pfnIsHardReset)
3863 {
3864 Assert(pFwReg->pfnIsHardReset);
3865 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3866 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3867 return VERR_INVALID_PARAMETER;
3868 }
3869
3870 if (!ppFwHlp)
3871 {
3872 Assert(ppFwHlp);
3873 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (ppFwHlp)\n",
3874 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3875 return VERR_INVALID_PARAMETER;
3876 }
3877
3878 /*
3879 * Only one DMA device.
3880 */
3881 PVM pVM = pDevIns->Internal.s.pVMR3;
3882 if (pVM->pdm.s.pFirmware)
3883 {
3884 AssertMsgFailed(("Only one firmware device is supported!\n"));
3885 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
3886 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3887 return VERR_INVALID_PARAMETER;
3888 }
3889
3890 /*
3891 * Allocate and initialize pci bus structure.
3892 */
3893 int rc = VINF_SUCCESS;
3894 PPDMFW pFirmware = (PPDMFW)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pFirmware));
3895 if (pFirmware)
3896 {
3897 pFirmware->pDevIns = pDevIns;
3898 pFirmware->Reg = *pFwReg;
3899 pVM->pdm.s.pFirmware = pFirmware;
3900
3901 /* set the helper pointer. */
3902 *ppFwHlp = &g_pdmR3DevFirmwareHlp;
3903 Log(("PDM: Registered firmware device '%s'/%d pDevIns=%p\n",
3904 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3905 }
3906 else
3907 rc = VERR_NO_MEMORY;
3908
3909 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
3910 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3911 return rc;
3912}
3913
3914
3915/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
3916static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
3917{
3918 PDMDEV_ASSERT_DEVINS(pDevIns);
3919 PVM pVM = pDevIns->Internal.s.pVMR3;
3920 VM_ASSERT_EMT(pVM);
3921 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: fFlags=%#x VM_FF_RESET %d -> 1\n",
3922 pDevIns->pReg->szName, pDevIns->iInstance, fFlags, VM_FF_IS_SET(pVM, VM_FF_RESET)));
3923
3924 /*
3925 * We postpone this operation because we're likely to be inside a I/O instruction
3926 * and the EIP will be updated when we return.
3927 * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
3928 */
3929 bool fHaltOnReset;
3930 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
3931 if (RT_SUCCESS(rc) && fHaltOnReset)
3932 {
3933 Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
3934 rc = VINF_EM_HALT;
3935 }
3936 else
3937 {
3938 pVM->pdm.s.fResetFlags = fFlags;
3939 VM_FF_SET(pVM, VM_FF_RESET);
3940 rc = VINF_EM_RESET;
3941 }
3942
3943 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3944 return rc;
3945}
3946
3947
3948/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
3949static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
3950{
3951 int rc;
3952 PDMDEV_ASSERT_DEVINS(pDevIns);
3953 PVM pVM = pDevIns->Internal.s.pVMR3;
3954 VM_ASSERT_EMT(pVM);
3955 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
3956 pDevIns->pReg->szName, pDevIns->iInstance));
3957
3958 /** @todo Always take the SMP path - fewer code paths. */
3959 if (pVM->cCpus > 1)
3960 {
3961 /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
3962 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3Suspend, 2, pVM->pUVM, VMSUSPENDREASON_VM);
3963 AssertRC(rc);
3964 rc = VINF_EM_SUSPEND;
3965 }
3966 else
3967 rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
3968
3969 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3970 return rc;
3971}
3972
3973
3974/**
3975 * Worker for pdmR3DevHlp_VMSuspendSaveAndPowerOff that is invoked via a queued
3976 * EMT request to avoid deadlocks.
3977 *
3978 * @returns VBox status code fit for scheduling.
3979 * @param pVM The cross context VM structure.
3980 * @param pDevIns The device that triggered this action.
3981 */
3982static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker(PVM pVM, PPDMDEVINS pDevIns)
3983{
3984 /*
3985 * Suspend the VM first then do the saving.
3986 */
3987 int rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
3988 if (RT_SUCCESS(rc))
3989 {
3990 PUVM pUVM = pVM->pUVM;
3991 rc = pUVM->pVmm2UserMethods->pfnSaveState(pVM->pUVM->pVmm2UserMethods, pUVM);
3992
3993 /*
3994 * On success, power off the VM, on failure we'll leave it suspended.
3995 */
3996 if (RT_SUCCESS(rc))
3997 {
3998 rc = VMR3PowerOff(pVM->pUVM);
3999 if (RT_FAILURE(rc))
4000 LogRel(("%s/SSP: VMR3PowerOff failed: %Rrc\n", pDevIns->pReg->szName, rc));
4001 }
4002 else
4003 LogRel(("%s/SSP: pfnSaveState failed: %Rrc\n", pDevIns->pReg->szName, rc));
4004 }
4005 else
4006 LogRel(("%s/SSP: Suspend failed: %Rrc\n", pDevIns->pReg->szName, rc));
4007 return rc;
4008}
4009
4010
4011/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
4012static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
4013{
4014 PDMDEV_ASSERT_DEVINS(pDevIns);
4015 PVM pVM = pDevIns->Internal.s.pVMR3;
4016 VM_ASSERT_EMT(pVM);
4017 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d:\n",
4018 pDevIns->pReg->szName, pDevIns->iInstance));
4019
4020 int rc;
4021 if ( pVM->pUVM->pVmm2UserMethods
4022 && pVM->pUVM->pVmm2UserMethods->pfnSaveState)
4023 {
4024 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker, 2, pVM, pDevIns);
4025 if (RT_SUCCESS(rc))
4026 {
4027 LogRel(("%s: Suspending, Saving and Powering Off the VM\n", pDevIns->pReg->szName));
4028 rc = VINF_EM_SUSPEND;
4029 }
4030 }
4031 else
4032 rc = VERR_NOT_SUPPORTED;
4033
4034 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4035 return rc;
4036}
4037
4038
4039/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
4040static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
4041{
4042 int rc;
4043 PDMDEV_ASSERT_DEVINS(pDevIns);
4044 PVM pVM = pDevIns->Internal.s.pVMR3;
4045 VM_ASSERT_EMT(pVM);
4046 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
4047 pDevIns->pReg->szName, pDevIns->iInstance));
4048
4049 /** @todo Always take the SMP path - fewer code paths. */
4050 if (pVM->cCpus > 1)
4051 {
4052 /* We might be holding locks here and could cause a deadlock since
4053 VMR3PowerOff rendezvous with the other CPUs. */
4054 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3PowerOff, 1, pVM->pUVM);
4055 AssertRC(rc);
4056 /* Set the VCPU state to stopped here as well to make sure no
4057 inconsistency with the EM state occurs. */
4058 VMCPU_SET_STATE(VMMGetCpu(pVM), VMCPUSTATE_STOPPED);
4059 rc = VINF_EM_OFF;
4060 }
4061 else
4062 rc = VMR3PowerOff(pVM->pUVM);
4063
4064 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4065 return rc;
4066}
4067
4068
4069/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
4070static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
4071{
4072 PDMDEV_ASSERT_DEVINS(pDevIns);
4073 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4074
4075 bool fRc = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pVMR3));
4076
4077 LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pReg->szName, pDevIns->iInstance, fRc));
4078 return fRc;
4079}
4080
4081
4082/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
4083static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
4084{
4085 PDMDEV_ASSERT_DEVINS(pDevIns);
4086 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4087 LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, fEnable));
4088 PGMR3PhysSetA20(VMMGetCpu(pDevIns->Internal.s.pVMR3), fEnable);
4089}
4090
4091
4092/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
4093static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
4094 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
4095{
4096 PDMDEV_ASSERT_DEVINS(pDevIns);
4097 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4098
4099 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
4100 pDevIns->pReg->szName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
4101 AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
4102
4103 CPUMGetGuestCpuId(VMMGetCpu(pDevIns->Internal.s.pVMR3), iLeaf, 0 /*iSubLeaf*/, pEax, pEbx, pEcx, pEdx);
4104
4105 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
4106 pDevIns->pReg->szName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
4107}
4108
4109
4110/**
4111 * The device helper structure for trusted devices.
4112 */
4113const PDMDEVHLPR3 g_pdmR3DevHlpTrusted =
4114{
4115 PDM_DEVHLPR3_VERSION,
4116 pdmR3DevHlp_IoPortCreateEx,
4117 pdmR3DevHlp_IoPortMap,
4118 pdmR3DevHlp_IoPortUnmap,
4119 pdmR3DevHlp_IOPortRegister,
4120 pdmR3DevHlp_IOPortRegisterRC,
4121 pdmR3DevHlp_IOPortRegisterR0,
4122 pdmR3DevHlp_IOPortDeregister,
4123 pdmR3DevHlp_MmioCreateEx,
4124 pdmR3DevHlp_MmioMap,
4125 pdmR3DevHlp_MmioUnmap,
4126 pdmR3DevHlp_MmioReduce,
4127 pdmR3DevHlp_MMIORegister,
4128 pdmR3DevHlp_MMIORegisterRC,
4129 pdmR3DevHlp_MMIORegisterR0,
4130 pdmR3DevHlp_MMIODeregister,
4131 pdmR3DevHlp_MMIO2Register,
4132 pdmR3DevHlp_MMIOExPreRegister,
4133 pdmR3DevHlp_MMIOExDeregister,
4134 pdmR3DevHlp_MMIOExMap,
4135 pdmR3DevHlp_MMIOExUnmap,
4136 pdmR3DevHlp_MMIOExReduce,
4137 pdmR3DevHlp_MMHyperMapMMIO2,
4138 pdmR3DevHlp_MMIO2MapKernel,
4139 pdmR3DevHlp_ROMRegister,
4140 pdmR3DevHlp_ROMProtectShadow,
4141 pdmR3DevHlp_SSMRegister,
4142 SSMR3PutStruct,
4143 SSMR3PutStructEx,
4144 SSMR3PutBool,
4145 SSMR3PutU8,
4146 SSMR3PutS8,
4147 SSMR3PutU16,
4148 SSMR3PutS16,
4149 SSMR3PutU32,
4150 SSMR3PutS32,
4151 SSMR3PutU64,
4152 SSMR3PutS64,
4153 SSMR3PutU128,
4154 SSMR3PutS128,
4155 SSMR3PutUInt,
4156 SSMR3PutSInt,
4157 SSMR3PutGCUInt,
4158 SSMR3PutGCUIntReg,
4159 SSMR3PutGCPhys32,
4160 SSMR3PutGCPhys64,
4161 SSMR3PutGCPhys,
4162 SSMR3PutGCPtr,
4163 SSMR3PutGCUIntPtr,
4164 SSMR3PutRCPtr,
4165 SSMR3PutIOPort,
4166 SSMR3PutSel,
4167 SSMR3PutMem,
4168 SSMR3PutStrZ,
4169 SSMR3GetStruct,
4170 SSMR3GetStructEx,
4171 SSMR3GetBool,
4172 SSMR3GetU8,
4173 SSMR3GetS8,
4174 SSMR3GetU16,
4175 SSMR3GetS16,
4176 SSMR3GetU32,
4177 SSMR3GetS32,
4178 SSMR3GetU64,
4179 SSMR3GetS64,
4180 SSMR3GetU128,
4181 SSMR3GetS128,
4182 SSMR3GetUInt,
4183 SSMR3GetSInt,
4184 SSMR3GetGCUInt,
4185 SSMR3GetGCUIntReg,
4186 SSMR3GetGCPhys32,
4187 SSMR3GetGCPhys64,
4188 SSMR3GetGCPhys,
4189 SSMR3GetGCPtr,
4190 SSMR3GetGCUIntPtr,
4191 SSMR3GetRCPtr,
4192 SSMR3GetIOPort,
4193 SSMR3GetSel,
4194 SSMR3GetMem,
4195 SSMR3GetStrZ,
4196 SSMR3GetStrZEx,
4197 SSMR3Skip,
4198 SSMR3SkipToEndOfUnit,
4199 SSMR3SetLoadError,
4200 SSMR3SetLoadErrorV,
4201 SSMR3SetCfgError,
4202 SSMR3SetCfgErrorV,
4203 SSMR3HandleGetStatus,
4204 SSMR3HandleGetAfter,
4205 SSMR3HandleIsLiveSave,
4206 SSMR3HandleMaxDowntime,
4207 SSMR3HandleHostBits,
4208 SSMR3HandleRevision,
4209 SSMR3HandleVersion,
4210 pdmR3DevHlp_TMTimerCreate,
4211 pdmR3DevHlp_TimerCreate,
4212 pdmR3DevHlp_TimerToPtr,
4213 pdmR3DevHlp_TimerFromMicro,
4214 pdmR3DevHlp_TimerFromMilli,
4215 pdmR3DevHlp_TimerFromNano,
4216 pdmR3DevHlp_TimerGet,
4217 pdmR3DevHlp_TimerGetFreq,
4218 pdmR3DevHlp_TimerGetNano,
4219 pdmR3DevHlp_TimerIsActive,
4220 pdmR3DevHlp_TimerIsLockOwner,
4221 pdmR3DevHlp_TimerLock,
4222 pdmR3DevHlp_TimerSet,
4223 pdmR3DevHlp_TimerSetFrequencyHint,
4224 pdmR3DevHlp_TimerSetMicro,
4225 pdmR3DevHlp_TimerSetMillies,
4226 pdmR3DevHlp_TimerSetNano,
4227 pdmR3DevHlp_TimerSetRelative,
4228 pdmR3DevHlp_TimerStop,
4229 pdmR3DevHlp_TimerUnlock,
4230 pdmR3DevHlp_TimerSave,
4231 pdmR3DevHlp_TimerLoad,
4232 pdmR3DevHlp_TMUtcNow,
4233 CFGMR3Exists,
4234 CFGMR3QueryType,
4235 CFGMR3QuerySize,
4236 CFGMR3QueryInteger,
4237 CFGMR3QueryIntegerDef,
4238 CFGMR3QueryString,
4239 CFGMR3QueryStringDef,
4240 CFGMR3QueryBytes,
4241 CFGMR3QueryU64,
4242 CFGMR3QueryU64Def,
4243 CFGMR3QueryS64,
4244 CFGMR3QueryS64Def,
4245 CFGMR3QueryU32,
4246 CFGMR3QueryU32Def,
4247 CFGMR3QueryS32,
4248 CFGMR3QueryS32Def,
4249 CFGMR3QueryU16,
4250 CFGMR3QueryU16Def,
4251 CFGMR3QueryS16,
4252 CFGMR3QueryS16Def,
4253 CFGMR3QueryU8,
4254 CFGMR3QueryU8Def,
4255 CFGMR3QueryS8,
4256 CFGMR3QueryS8Def,
4257 CFGMR3QueryBool,
4258 CFGMR3QueryBoolDef,
4259 CFGMR3QueryPort,
4260 CFGMR3QueryPortDef,
4261 CFGMR3QueryUInt,
4262 CFGMR3QueryUIntDef,
4263 CFGMR3QuerySInt,
4264 CFGMR3QuerySIntDef,
4265 CFGMR3QueryPtr,
4266 CFGMR3QueryPtrDef,
4267 CFGMR3QueryGCPtr,
4268 CFGMR3QueryGCPtrDef,
4269 CFGMR3QueryGCPtrU,
4270 CFGMR3QueryGCPtrUDef,
4271 CFGMR3QueryGCPtrS,
4272 CFGMR3QueryGCPtrSDef,
4273 CFGMR3QueryStringAlloc,
4274 CFGMR3QueryStringAllocDef,
4275 CFGMR3GetParent,
4276 CFGMR3GetChild,
4277 CFGMR3GetChildF,
4278 CFGMR3GetChildFV,
4279 CFGMR3GetFirstChild,
4280 CFGMR3GetNextChild,
4281 CFGMR3GetName,
4282 CFGMR3GetNameLen,
4283 CFGMR3AreChildrenValid,
4284 CFGMR3GetFirstValue,
4285 CFGMR3GetNextValue,
4286 CFGMR3GetValueName,
4287 CFGMR3GetValueNameLen,
4288 CFGMR3GetValueType,
4289 CFGMR3AreValuesValid,
4290 CFGMR3ValidateConfig,
4291 pdmR3DevHlp_PhysRead,
4292 pdmR3DevHlp_PhysWrite,
4293 pdmR3DevHlp_PhysGCPhys2CCPtr,
4294 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4295 pdmR3DevHlp_PhysReleasePageMappingLock,
4296 pdmR3DevHlp_PhysReadGCVirt,
4297 pdmR3DevHlp_PhysWriteGCVirt,
4298 pdmR3DevHlp_PhysGCPtr2GCPhys,
4299 pdmR3DevHlp_MMHeapAlloc,
4300 pdmR3DevHlp_MMHeapAllocZ,
4301 pdmR3DevHlp_MMHeapFree,
4302 pdmR3DevHlp_VMState,
4303 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4304 pdmR3DevHlp_VMSetError,
4305 pdmR3DevHlp_VMSetErrorV,
4306 pdmR3DevHlp_VMSetRuntimeError,
4307 pdmR3DevHlp_VMSetRuntimeErrorV,
4308 pdmR3DevHlp_DBGFStopV,
4309 pdmR3DevHlp_DBGFInfoRegister,
4310 pdmR3DevHlp_DBGFInfoRegisterArgv,
4311 pdmR3DevHlp_DBGFRegRegister,
4312 pdmR3DevHlp_DBGFTraceBuf,
4313 pdmR3DevHlp_STAMRegister,
4314 pdmR3DevHlp_STAMRegisterF,
4315 pdmR3DevHlp_STAMRegisterV,
4316 pdmR3DevHlp_PCIRegister,
4317 pdmR3DevHlp_PCIRegisterMsi,
4318 pdmR3DevHlp_PCIIORegionRegister,
4319 pdmR3DevHlp_PCISetConfigCallbacks,
4320 pdmR3DevHlp_PCIPhysRead,
4321 pdmR3DevHlp_PCIPhysWrite,
4322 pdmR3DevHlp_PCISetIrq,
4323 pdmR3DevHlp_PCISetIrqNoWait,
4324 pdmR3DevHlp_ISASetIrq,
4325 pdmR3DevHlp_ISASetIrqNoWait,
4326 pdmR3DevHlp_IoApicSendMsi,
4327 pdmR3DevHlp_DriverAttach,
4328 pdmR3DevHlp_DriverDetach,
4329 pdmR3DevHlp_QueueCreate,
4330 pdmR3DevHlp_CritSectInit,
4331 pdmR3DevHlp_CritSectGetNop,
4332 pdmR3DevHlp_CritSectGetNopR0,
4333 pdmR3DevHlp_CritSectGetNopRC,
4334 pdmR3DevHlp_SetDeviceCritSect,
4335 pdmR3DevHlp_CritSectYield,
4336 pdmR3DevHlp_CritSectEnter,
4337 pdmR3DevHlp_CritSectEnterDebug,
4338 pdmR3DevHlp_CritSectTryEnter,
4339 pdmR3DevHlp_CritSectTryEnterDebug,
4340 pdmR3DevHlp_CritSectLeave,
4341 pdmR3DevHlp_CritSectIsOwner,
4342 pdmR3DevHlp_CritSectIsInitialized,
4343 pdmR3DevHlp_CritSectHasWaiters,
4344 pdmR3DevHlp_CritSectGetRecursion,
4345 pdmR3DevHlp_ThreadCreate,
4346 pdmR3DevHlp_SetAsyncNotification,
4347 pdmR3DevHlp_AsyncNotificationCompleted,
4348 pdmR3DevHlp_RTCRegister,
4349 pdmR3DevHlp_PCIBusRegister,
4350 pdmR3DevHlp_PICRegister,
4351 pdmR3DevHlp_APICRegister,
4352 pdmR3DevHlp_IOAPICRegister,
4353 pdmR3DevHlp_HPETRegister,
4354 pdmR3DevHlp_PciRawRegister,
4355 pdmR3DevHlp_DMACRegister,
4356 pdmR3DevHlp_DMARegister,
4357 pdmR3DevHlp_DMAReadMemory,
4358 pdmR3DevHlp_DMAWriteMemory,
4359 pdmR3DevHlp_DMASetDREQ,
4360 pdmR3DevHlp_DMAGetChannelMode,
4361 pdmR3DevHlp_DMASchedule,
4362 pdmR3DevHlp_CMOSWrite,
4363 pdmR3DevHlp_CMOSRead,
4364 pdmR3DevHlp_AssertEMT,
4365 pdmR3DevHlp_AssertOther,
4366 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4367 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4368 pdmR3DevHlp_CallR0,
4369 pdmR3DevHlp_VMGetSuspendReason,
4370 pdmR3DevHlp_VMGetResumeReason,
4371 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4372 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4373 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4374 pdmR3DevHlp_MMIOExChangeRegionNo,
4375 0,
4376 0,
4377 0,
4378 0,
4379 0,
4380 0,
4381 0,
4382 0,
4383 0,
4384 0,
4385 pdmR3DevHlp_GetUVM,
4386 pdmR3DevHlp_GetVM,
4387 pdmR3DevHlp_GetVMCPU,
4388 pdmR3DevHlp_GetCurrentCpuId,
4389 pdmR3DevHlp_RegisterVMMDevHeap,
4390 pdmR3DevHlp_FirmwareRegister,
4391 pdmR3DevHlp_VMReset,
4392 pdmR3DevHlp_VMSuspend,
4393 pdmR3DevHlp_VMSuspendSaveAndPowerOff,
4394 pdmR3DevHlp_VMPowerOff,
4395 pdmR3DevHlp_A20IsEnabled,
4396 pdmR3DevHlp_A20Set,
4397 pdmR3DevHlp_GetCpuId,
4398 pdmR3DevHlp_TMTimeVirtGet,
4399 pdmR3DevHlp_TMTimeVirtGetFreq,
4400 pdmR3DevHlp_TMTimeVirtGetNano,
4401 pdmR3DevHlp_GetSupDrvSession,
4402 pdmR3DevHlp_QueryGenericUserObject,
4403 PDM_DEVHLPR3_VERSION /* the end */
4404};
4405
4406
4407
4408
4409/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
4410static DECLCALLBACK(PUVM) pdmR3DevHlp_Untrusted_GetUVM(PPDMDEVINS pDevIns)
4411{
4412 PDMDEV_ASSERT_DEVINS(pDevIns);
4413 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4414 return NULL;
4415}
4416
4417
4418/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
4419static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
4420{
4421 PDMDEV_ASSERT_DEVINS(pDevIns);
4422 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4423 return NULL;
4424}
4425
4426
4427/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
4428static DECLCALLBACK(PVMCPU) pdmR3DevHlp_Untrusted_GetVMCPU(PPDMDEVINS pDevIns)
4429{
4430 PDMDEV_ASSERT_DEVINS(pDevIns);
4431 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4432 return NULL;
4433}
4434
4435
4436/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
4437static DECLCALLBACK(VMCPUID) pdmR3DevHlp_Untrusted_GetCurrentCpuId(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 NIL_VMCPUID;
4442}
4443
4444
4445/** @interface_method_impl{PDMDEVHLPR3,pfnRegisterVMMDevHeap} */
4446static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys,
4447 RTR3PTR pvHeap, unsigned cbHeap)
4448{
4449 PDMDEV_ASSERT_DEVINS(pDevIns);
4450 NOREF(GCPhys); NOREF(pvHeap); NOREF(cbHeap);
4451 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4452 return VERR_ACCESS_DENIED;
4453}
4454
4455
4456/** @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister} */
4457static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
4458{
4459 PDMDEV_ASSERT_DEVINS(pDevIns);
4460 NOREF(pFwReg); NOREF(ppFwHlp);
4461 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4462 return VERR_ACCESS_DENIED;
4463}
4464
4465
4466/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
4467static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
4468{
4469 PDMDEV_ASSERT_DEVINS(pDevIns); NOREF(fFlags);
4470 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4471 return VERR_ACCESS_DENIED;
4472}
4473
4474
4475/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
4476static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
4477{
4478 PDMDEV_ASSERT_DEVINS(pDevIns);
4479 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4480 return VERR_ACCESS_DENIED;
4481}
4482
4483
4484/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
4485static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
4486{
4487 PDMDEV_ASSERT_DEVINS(pDevIns);
4488 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4489 return VERR_ACCESS_DENIED;
4490}
4491
4492
4493/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
4494static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
4495{
4496 PDMDEV_ASSERT_DEVINS(pDevIns);
4497 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4498 return VERR_ACCESS_DENIED;
4499}
4500
4501
4502/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
4503static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
4504{
4505 PDMDEV_ASSERT_DEVINS(pDevIns);
4506 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4507 return false;
4508}
4509
4510
4511/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
4512static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
4513{
4514 PDMDEV_ASSERT_DEVINS(pDevIns);
4515 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4516 NOREF(fEnable);
4517}
4518
4519
4520/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
4521static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
4522 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
4523{
4524 PDMDEV_ASSERT_DEVINS(pDevIns);
4525 NOREF(iLeaf); NOREF(pEax); NOREF(pEbx); NOREF(pEcx); NOREF(pEdx);
4526 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4527}
4528
4529
4530/** @interface_method_impl{PDMDEVHLPR3,pfnGetSupDrvSession} */
4531static DECLCALLBACK(PSUPDRVSESSION) pdmR3DevHlp_Untrusted_GetSupDrvSession(PPDMDEVINS pDevIns)
4532{
4533 PDMDEV_ASSERT_DEVINS(pDevIns);
4534 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4535 return (PSUPDRVSESSION)0;
4536}
4537
4538
4539/** @interface_method_impl{PDMDEVHLPR3,pfnQueryGenericUserObject} */
4540static DECLCALLBACK(void *) pdmR3DevHlp_Untrusted_QueryGenericUserObject(PPDMDEVINS pDevIns, PCRTUUID pUuid)
4541{
4542 PDMDEV_ASSERT_DEVINS(pDevIns);
4543 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d %RTuuid\n",
4544 pDevIns->pReg->szName, pDevIns->iInstance, pUuid));
4545 return NULL;
4546}
4547
4548
4549/**
4550 * The device helper structure for non-trusted devices.
4551 */
4552const PDMDEVHLPR3 g_pdmR3DevHlpUnTrusted =
4553{
4554 PDM_DEVHLPR3_VERSION,
4555 pdmR3DevHlp_IoPortCreateEx,
4556 pdmR3DevHlp_IoPortMap,
4557 pdmR3DevHlp_IoPortUnmap,
4558 pdmR3DevHlp_IOPortRegister,
4559 pdmR3DevHlp_IOPortRegisterRC,
4560 pdmR3DevHlp_IOPortRegisterR0,
4561 pdmR3DevHlp_IOPortDeregister,
4562 pdmR3DevHlp_MmioCreateEx,
4563 pdmR3DevHlp_MmioMap,
4564 pdmR3DevHlp_MmioUnmap,
4565 pdmR3DevHlp_MmioReduce,
4566 pdmR3DevHlp_MMIORegister,
4567 pdmR3DevHlp_MMIORegisterRC,
4568 pdmR3DevHlp_MMIORegisterR0,
4569 pdmR3DevHlp_MMIODeregister,
4570 pdmR3DevHlp_MMIO2Register,
4571 pdmR3DevHlp_MMIOExPreRegister,
4572 pdmR3DevHlp_MMIOExDeregister,
4573 pdmR3DevHlp_MMIOExMap,
4574 pdmR3DevHlp_MMIOExUnmap,
4575 pdmR3DevHlp_MMIOExReduce,
4576 pdmR3DevHlp_MMHyperMapMMIO2,
4577 pdmR3DevHlp_MMIO2MapKernel,
4578 pdmR3DevHlp_ROMRegister,
4579 pdmR3DevHlp_ROMProtectShadow,
4580 pdmR3DevHlp_SSMRegister,
4581 SSMR3PutStruct,
4582 SSMR3PutStructEx,
4583 SSMR3PutBool,
4584 SSMR3PutU8,
4585 SSMR3PutS8,
4586 SSMR3PutU16,
4587 SSMR3PutS16,
4588 SSMR3PutU32,
4589 SSMR3PutS32,
4590 SSMR3PutU64,
4591 SSMR3PutS64,
4592 SSMR3PutU128,
4593 SSMR3PutS128,
4594 SSMR3PutUInt,
4595 SSMR3PutSInt,
4596 SSMR3PutGCUInt,
4597 SSMR3PutGCUIntReg,
4598 SSMR3PutGCPhys32,
4599 SSMR3PutGCPhys64,
4600 SSMR3PutGCPhys,
4601 SSMR3PutGCPtr,
4602 SSMR3PutGCUIntPtr,
4603 SSMR3PutRCPtr,
4604 SSMR3PutIOPort,
4605 SSMR3PutSel,
4606 SSMR3PutMem,
4607 SSMR3PutStrZ,
4608 SSMR3GetStruct,
4609 SSMR3GetStructEx,
4610 SSMR3GetBool,
4611 SSMR3GetU8,
4612 SSMR3GetS8,
4613 SSMR3GetU16,
4614 SSMR3GetS16,
4615 SSMR3GetU32,
4616 SSMR3GetS32,
4617 SSMR3GetU64,
4618 SSMR3GetS64,
4619 SSMR3GetU128,
4620 SSMR3GetS128,
4621 SSMR3GetUInt,
4622 SSMR3GetSInt,
4623 SSMR3GetGCUInt,
4624 SSMR3GetGCUIntReg,
4625 SSMR3GetGCPhys32,
4626 SSMR3GetGCPhys64,
4627 SSMR3GetGCPhys,
4628 SSMR3GetGCPtr,
4629 SSMR3GetGCUIntPtr,
4630 SSMR3GetRCPtr,
4631 SSMR3GetIOPort,
4632 SSMR3GetSel,
4633 SSMR3GetMem,
4634 SSMR3GetStrZ,
4635 SSMR3GetStrZEx,
4636 SSMR3Skip,
4637 SSMR3SkipToEndOfUnit,
4638 SSMR3SetLoadError,
4639 SSMR3SetLoadErrorV,
4640 SSMR3SetCfgError,
4641 SSMR3SetCfgErrorV,
4642 SSMR3HandleGetStatus,
4643 SSMR3HandleGetAfter,
4644 SSMR3HandleIsLiveSave,
4645 SSMR3HandleMaxDowntime,
4646 SSMR3HandleHostBits,
4647 SSMR3HandleRevision,
4648 SSMR3HandleVersion,
4649 pdmR3DevHlp_TMTimerCreate,
4650 pdmR3DevHlp_TimerCreate,
4651 pdmR3DevHlp_TimerToPtr,
4652 pdmR3DevHlp_TimerFromMicro,
4653 pdmR3DevHlp_TimerFromMilli,
4654 pdmR3DevHlp_TimerFromNano,
4655 pdmR3DevHlp_TimerGet,
4656 pdmR3DevHlp_TimerGetFreq,
4657 pdmR3DevHlp_TimerGetNano,
4658 pdmR3DevHlp_TimerIsActive,
4659 pdmR3DevHlp_TimerIsLockOwner,
4660 pdmR3DevHlp_TimerLock,
4661 pdmR3DevHlp_TimerSet,
4662 pdmR3DevHlp_TimerSetFrequencyHint,
4663 pdmR3DevHlp_TimerSetMicro,
4664 pdmR3DevHlp_TimerSetMillies,
4665 pdmR3DevHlp_TimerSetNano,
4666 pdmR3DevHlp_TimerSetRelative,
4667 pdmR3DevHlp_TimerStop,
4668 pdmR3DevHlp_TimerUnlock,
4669 pdmR3DevHlp_TimerSave,
4670 pdmR3DevHlp_TimerLoad,
4671 pdmR3DevHlp_TMUtcNow,
4672 CFGMR3Exists,
4673 CFGMR3QueryType,
4674 CFGMR3QuerySize,
4675 CFGMR3QueryInteger,
4676 CFGMR3QueryIntegerDef,
4677 CFGMR3QueryString,
4678 CFGMR3QueryStringDef,
4679 CFGMR3QueryBytes,
4680 CFGMR3QueryU64,
4681 CFGMR3QueryU64Def,
4682 CFGMR3QueryS64,
4683 CFGMR3QueryS64Def,
4684 CFGMR3QueryU32,
4685 CFGMR3QueryU32Def,
4686 CFGMR3QueryS32,
4687 CFGMR3QueryS32Def,
4688 CFGMR3QueryU16,
4689 CFGMR3QueryU16Def,
4690 CFGMR3QueryS16,
4691 CFGMR3QueryS16Def,
4692 CFGMR3QueryU8,
4693 CFGMR3QueryU8Def,
4694 CFGMR3QueryS8,
4695 CFGMR3QueryS8Def,
4696 CFGMR3QueryBool,
4697 CFGMR3QueryBoolDef,
4698 CFGMR3QueryPort,
4699 CFGMR3QueryPortDef,
4700 CFGMR3QueryUInt,
4701 CFGMR3QueryUIntDef,
4702 CFGMR3QuerySInt,
4703 CFGMR3QuerySIntDef,
4704 CFGMR3QueryPtr,
4705 CFGMR3QueryPtrDef,
4706 CFGMR3QueryGCPtr,
4707 CFGMR3QueryGCPtrDef,
4708 CFGMR3QueryGCPtrU,
4709 CFGMR3QueryGCPtrUDef,
4710 CFGMR3QueryGCPtrS,
4711 CFGMR3QueryGCPtrSDef,
4712 CFGMR3QueryStringAlloc,
4713 CFGMR3QueryStringAllocDef,
4714 CFGMR3GetParent,
4715 CFGMR3GetChild,
4716 CFGMR3GetChildF,
4717 CFGMR3GetChildFV,
4718 CFGMR3GetFirstChild,
4719 CFGMR3GetNextChild,
4720 CFGMR3GetName,
4721 CFGMR3GetNameLen,
4722 CFGMR3AreChildrenValid,
4723 CFGMR3GetFirstValue,
4724 CFGMR3GetNextValue,
4725 CFGMR3GetValueName,
4726 CFGMR3GetValueNameLen,
4727 CFGMR3GetValueType,
4728 CFGMR3AreValuesValid,
4729 CFGMR3ValidateConfig,
4730 pdmR3DevHlp_PhysRead,
4731 pdmR3DevHlp_PhysWrite,
4732 pdmR3DevHlp_PhysGCPhys2CCPtr,
4733 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4734 pdmR3DevHlp_PhysReleasePageMappingLock,
4735 pdmR3DevHlp_PhysReadGCVirt,
4736 pdmR3DevHlp_PhysWriteGCVirt,
4737 pdmR3DevHlp_PhysGCPtr2GCPhys,
4738 pdmR3DevHlp_MMHeapAlloc,
4739 pdmR3DevHlp_MMHeapAllocZ,
4740 pdmR3DevHlp_MMHeapFree,
4741 pdmR3DevHlp_VMState,
4742 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4743 pdmR3DevHlp_VMSetError,
4744 pdmR3DevHlp_VMSetErrorV,
4745 pdmR3DevHlp_VMSetRuntimeError,
4746 pdmR3DevHlp_VMSetRuntimeErrorV,
4747 pdmR3DevHlp_DBGFStopV,
4748 pdmR3DevHlp_DBGFInfoRegister,
4749 pdmR3DevHlp_DBGFInfoRegisterArgv,
4750 pdmR3DevHlp_DBGFRegRegister,
4751 pdmR3DevHlp_DBGFTraceBuf,
4752 pdmR3DevHlp_STAMRegister,
4753 pdmR3DevHlp_STAMRegisterF,
4754 pdmR3DevHlp_STAMRegisterV,
4755 pdmR3DevHlp_PCIRegister,
4756 pdmR3DevHlp_PCIRegisterMsi,
4757 pdmR3DevHlp_PCIIORegionRegister,
4758 pdmR3DevHlp_PCISetConfigCallbacks,
4759 pdmR3DevHlp_PCIPhysRead,
4760 pdmR3DevHlp_PCIPhysWrite,
4761 pdmR3DevHlp_PCISetIrq,
4762 pdmR3DevHlp_PCISetIrqNoWait,
4763 pdmR3DevHlp_ISASetIrq,
4764 pdmR3DevHlp_ISASetIrqNoWait,
4765 pdmR3DevHlp_IoApicSendMsi,
4766 pdmR3DevHlp_DriverAttach,
4767 pdmR3DevHlp_DriverDetach,
4768 pdmR3DevHlp_QueueCreate,
4769 pdmR3DevHlp_CritSectInit,
4770 pdmR3DevHlp_CritSectGetNop,
4771 pdmR3DevHlp_CritSectGetNopR0,
4772 pdmR3DevHlp_CritSectGetNopRC,
4773 pdmR3DevHlp_SetDeviceCritSect,
4774 pdmR3DevHlp_CritSectYield,
4775 pdmR3DevHlp_CritSectEnter,
4776 pdmR3DevHlp_CritSectEnterDebug,
4777 pdmR3DevHlp_CritSectTryEnter,
4778 pdmR3DevHlp_CritSectTryEnterDebug,
4779 pdmR3DevHlp_CritSectLeave,
4780 pdmR3DevHlp_CritSectIsOwner,
4781 pdmR3DevHlp_CritSectIsInitialized,
4782 pdmR3DevHlp_CritSectHasWaiters,
4783 pdmR3DevHlp_CritSectGetRecursion,
4784 pdmR3DevHlp_ThreadCreate,
4785 pdmR3DevHlp_SetAsyncNotification,
4786 pdmR3DevHlp_AsyncNotificationCompleted,
4787 pdmR3DevHlp_RTCRegister,
4788 pdmR3DevHlp_PCIBusRegister,
4789 pdmR3DevHlp_PICRegister,
4790 pdmR3DevHlp_APICRegister,
4791 pdmR3DevHlp_IOAPICRegister,
4792 pdmR3DevHlp_HPETRegister,
4793 pdmR3DevHlp_PciRawRegister,
4794 pdmR3DevHlp_DMACRegister,
4795 pdmR3DevHlp_DMARegister,
4796 pdmR3DevHlp_DMAReadMemory,
4797 pdmR3DevHlp_DMAWriteMemory,
4798 pdmR3DevHlp_DMASetDREQ,
4799 pdmR3DevHlp_DMAGetChannelMode,
4800 pdmR3DevHlp_DMASchedule,
4801 pdmR3DevHlp_CMOSWrite,
4802 pdmR3DevHlp_CMOSRead,
4803 pdmR3DevHlp_AssertEMT,
4804 pdmR3DevHlp_AssertOther,
4805 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4806 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4807 pdmR3DevHlp_CallR0,
4808 pdmR3DevHlp_VMGetSuspendReason,
4809 pdmR3DevHlp_VMGetResumeReason,
4810 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4811 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4812 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4813 pdmR3DevHlp_MMIOExChangeRegionNo,
4814 0,
4815 0,
4816 0,
4817 0,
4818 0,
4819 0,
4820 0,
4821 0,
4822 0,
4823 0,
4824 pdmR3DevHlp_Untrusted_GetUVM,
4825 pdmR3DevHlp_Untrusted_GetVM,
4826 pdmR3DevHlp_Untrusted_GetVMCPU,
4827 pdmR3DevHlp_Untrusted_GetCurrentCpuId,
4828 pdmR3DevHlp_Untrusted_RegisterVMMDevHeap,
4829 pdmR3DevHlp_Untrusted_FirmwareRegister,
4830 pdmR3DevHlp_Untrusted_VMReset,
4831 pdmR3DevHlp_Untrusted_VMSuspend,
4832 pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff,
4833 pdmR3DevHlp_Untrusted_VMPowerOff,
4834 pdmR3DevHlp_Untrusted_A20IsEnabled,
4835 pdmR3DevHlp_Untrusted_A20Set,
4836 pdmR3DevHlp_Untrusted_GetCpuId,
4837 pdmR3DevHlp_TMTimeVirtGet,
4838 pdmR3DevHlp_TMTimeVirtGetFreq,
4839 pdmR3DevHlp_TMTimeVirtGetNano,
4840 pdmR3DevHlp_Untrusted_GetSupDrvSession,
4841 pdmR3DevHlp_Untrusted_QueryGenericUserObject,
4842 PDM_DEVHLPR3_VERSION /* the end */
4843};
4844
4845
4846
4847/**
4848 * Queue consumer callback for internal component.
4849 *
4850 * @returns Success indicator.
4851 * If false the item will not be removed and the flushing will stop.
4852 * @param pVM The cross context VM structure.
4853 * @param pItem The item to consume. Upon return this item will be freed.
4854 */
4855DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
4856{
4857 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
4858 LogFlow(("pdmR3DevHlpQueueConsumer: enmOp=%d pDevIns=%p\n", pTask->enmOp, pTask->pDevInsR3));
4859 switch (pTask->enmOp)
4860 {
4861 case PDMDEVHLPTASKOP_ISA_SET_IRQ:
4862 PDMIsaSetIrq(pVM, pTask->u.IsaSetIRQ.iIrq, pTask->u.IsaSetIRQ.iLevel, pTask->u.IsaSetIRQ.uTagSrc);
4863 break;
4864
4865 case PDMDEVHLPTASKOP_PCI_SET_IRQ:
4866 {
4867 /* Same as pdmR3DevHlp_PCISetIrq, except we've got a tag already. */
4868 PPDMPCIDEV pPciDev = pTask->u.PciSetIRQ.pPciDevR3;
4869 if (pPciDev)
4870 {
4871 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
4872 AssertBreak(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
4873 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
4874
4875 pdmLock(pVM);
4876 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, pTask->u.PciSetIRQ.iIrq,
4877 pTask->u.PciSetIRQ.iLevel, pTask->u.PciSetIRQ.uTagSrc);
4878 pdmUnlock(pVM);
4879 }
4880 else
4881 AssertReleaseMsgFailed(("No PCI device registered!\n"));
4882 break;
4883 }
4884
4885 case PDMDEVHLPTASKOP_IOAPIC_SET_IRQ:
4886 PDMIoApicSetIrq(pVM, pTask->u.IoApicSetIRQ.iIrq, pTask->u.IoApicSetIRQ.iLevel, pTask->u.IoApicSetIRQ.uTagSrc);
4887 break;
4888
4889 default:
4890 AssertReleaseMsgFailed(("Invalid operation %d\n", pTask->enmOp));
4891 break;
4892 }
4893 return true;
4894}
4895
4896/** @} */
4897
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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