VirtualBox

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

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

VMM/TM: Experimenting with changing the signature of TMTimerFromMilli. Work in progress. bugref:9943

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

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