VirtualBox

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

最後變更 在這個檔案從87760是 87760,由 vboxsync 提交於 4 年 前

VMM/TM,VMM/DevHlp: Require flag on timers that are to be used in ring-0 (and while refactoring a counte flag to check that all timers have been checked). Removed obsolete timer device helpers. bugref:9943

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

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