VirtualBox

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

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

IOM: New I/O port registration code. bugref:9218

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

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