VirtualBox

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

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

VMM,Devices: Some PDM device model refactoring. bugref:9218

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

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