VirtualBox

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

Last change on this file since 86204 was 86070, checked in by vboxsync, 4 years ago

AMD IOMMU: bugref:9654 Fix accidentally not copying/initialize MSIMSG values. Fix using the translated memory address on
successful translations from the IOMMU. Fix not remapping any interrupt when IOMMU code is compiled but an IOMMU is not present.

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

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