VirtualBox

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

Last change on this file since 85972 was 85007, checked in by vboxsync, 4 years ago

AMD IOMMU: bugref:9654 PDM, Main: Changes for southbridge I/O APIC and related PCI address assignment.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 201.7 KB
Line 
1/* $Id: PDMDevHlp.cpp 85007 2020-06-30 17:19:25Z 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_FAILURE(rc))
1837 {
1838 Log(("pdmR3DevHlp_PCIPhysRead: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
1839 cbRead, rc));
1840 return rc;
1841 }
1842 }
1843#endif
1844
1845 return pDevIns->pHlpR3->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead, fFlags);
1846}
1847
1848
1849/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysWrite} */
1850static DECLCALLBACK(int)
1851pdmR3DevHlp_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags)
1852{
1853 PDMDEV_ASSERT_DEVINS(pDevIns);
1854 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1855 pPciDev = pDevIns->apPciDevs[0];
1856 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1857 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
1858
1859#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
1860 /*
1861 * Just check the busmaster setting here and forward the request to the generic read helper.
1862 */
1863 if (PCIDevIsBusmaster(pPciDev))
1864 { /* likely */ }
1865 else
1866 {
1867 Log(("pdmR3DevHlp_PCIPhysWrite: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n",
1868 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
1869 return VERR_PDM_NOT_PCI_BUS_MASTER;
1870 }
1871#endif
1872
1873#ifdef VBOX_WITH_IOMMU_AMD
1874 /** @todo IOMMU: Optimize/re-organize things here later. */
1875 PVM pVM = pDevIns->Internal.s.pVMR3;
1876 PPDMIOMMU pIommu = &pVM->pdm.s.aIommus[0];
1877 PPDMDEVINS pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
1878 if ( pDevInsIommu
1879 && pDevInsIommu != pDevIns)
1880 {
1881 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
1882 Assert(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
1883 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
1884
1885 RTGCPHYS GCPhysOut;
1886 uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
1887 int rc = pIommu->pfnMemWrite(pDevInsIommu, uDevId, GCPhys, cbWrite, &GCPhysOut);
1888 if (RT_FAILURE(rc))
1889 {
1890 Log(("pdmR3DevHlp_PCIPhysRead: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
1891 cbWrite, rc));
1892 return rc;
1893 }
1894 }
1895#endif
1896
1897 return pDevIns->pHlpR3->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite, fFlags);
1898}
1899
1900
1901/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrq} */
1902static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
1903{
1904 PDMDEV_ASSERT_DEVINS(pDevIns);
1905 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1906 pPciDev = pDevIns->apPciDevs[0];
1907 AssertReturnVoid(pPciDev);
1908 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
1909 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
1910 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
1911
1912 /*
1913 * Validate input.
1914 */
1915 Assert(iIrq == 0);
1916 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
1917
1918 /*
1919 * Must have a PCI device registered!
1920 */
1921 PVM pVM = pDevIns->Internal.s.pVMR3;
1922 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
1923 AssertReturnVoid(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
1924 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
1925
1926 pdmLock(pVM);
1927 uint32_t uTagSrc;
1928 if (iLevel & PDM_IRQ_LEVEL_HIGH)
1929 {
1930 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
1931 if (iLevel == PDM_IRQ_LEVEL_HIGH)
1932 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1933 else
1934 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1935 }
1936 else
1937 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
1938
1939 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel, uTagSrc);
1940
1941 if (iLevel == PDM_IRQ_LEVEL_LOW)
1942 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1943 pdmUnlock(pVM);
1944
1945 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1946}
1947
1948
1949/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrqNoWait} */
1950static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
1951{
1952 pdmR3DevHlp_PCISetIrq(pDevIns, pPciDev, iIrq, iLevel);
1953}
1954
1955
1956/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrq} */
1957static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
1958{
1959 PDMDEV_ASSERT_DEVINS(pDevIns);
1960 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
1961
1962 /*
1963 * Validate input.
1964 */
1965 Assert(iIrq < 16);
1966 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
1967
1968 PVM pVM = pDevIns->Internal.s.pVMR3;
1969
1970 /*
1971 * Do the job.
1972 */
1973 pdmLock(pVM);
1974 uint32_t uTagSrc;
1975 if (iLevel & PDM_IRQ_LEVEL_HIGH)
1976 {
1977 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
1978 if (iLevel == PDM_IRQ_LEVEL_HIGH)
1979 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1980 else
1981 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1982 }
1983 else
1984 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
1985
1986 PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */
1987
1988 if (iLevel == PDM_IRQ_LEVEL_LOW)
1989 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1990 pdmUnlock(pVM);
1991
1992 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1993}
1994
1995
1996/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrqNoWait} */
1997static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
1998{
1999 pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
2000}
2001
2002
2003/** @interface_method_impl{PDMDEVHLPR3,pfnDriverAttach} */
2004static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
2005{
2006 PDMDEV_ASSERT_DEVINS(pDevIns);
2007 PVM pVM = pDevIns->Internal.s.pVMR3;
2008 VM_ASSERT_EMT(pVM);
2009 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
2010 pDevIns->pReg->szName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
2011
2012 /*
2013 * Lookup the LUN, it might already be registered.
2014 */
2015 PPDMLUN pLunPrev = NULL;
2016 PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;
2017 for (; pLun; pLunPrev = pLun, pLun = pLun->pNext)
2018 if (pLun->iLun == iLun)
2019 break;
2020
2021 /*
2022 * Create the LUN if if wasn't found, else check if driver is already attached to it.
2023 */
2024 if (!pLun)
2025 {
2026 if ( !pBaseInterface
2027 || !pszDesc
2028 || !*pszDesc)
2029 {
2030 Assert(pBaseInterface);
2031 Assert(pszDesc || *pszDesc);
2032 return VERR_INVALID_PARAMETER;
2033 }
2034
2035 pLun = (PPDMLUN)MMR3HeapAlloc(pVM, MM_TAG_PDM_LUN, sizeof(*pLun));
2036 if (!pLun)
2037 return VERR_NO_MEMORY;
2038
2039 pLun->iLun = iLun;
2040 pLun->pNext = pLunPrev ? pLunPrev->pNext : NULL;
2041 pLun->pTop = NULL;
2042 pLun->pBottom = NULL;
2043 pLun->pDevIns = pDevIns;
2044 pLun->pUsbIns = NULL;
2045 pLun->pszDesc = pszDesc;
2046 pLun->pBase = pBaseInterface;
2047 if (!pLunPrev)
2048 pDevIns->Internal.s.pLunsR3 = pLun;
2049 else
2050 pLunPrev->pNext = pLun;
2051 Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
2052 iLun, pszDesc, pDevIns->pReg->szName, pDevIns->iInstance));
2053 }
2054 else if (pLun->pTop)
2055 {
2056 AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
2057 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
2058 return VERR_PDM_DRIVER_ALREADY_ATTACHED;
2059 }
2060 Assert(pLun->pBase == pBaseInterface);
2061
2062
2063 /*
2064 * Get the attached driver configuration.
2065 */
2066 int rc;
2067 PCFGMNODE pNode = CFGMR3GetChildF(pDevIns->Internal.s.pCfgHandle, "LUN#%u", iLun);
2068 if (pNode)
2069 rc = pdmR3DrvInstantiate(pVM, pNode, pBaseInterface, NULL /*pDrvAbove*/, pLun, ppBaseInterface);
2070 else
2071 rc = VERR_PDM_NO_ATTACHED_DRIVER;
2072
2073 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2074 return rc;
2075}
2076
2077
2078/** @interface_method_impl{PDMDEVHLPR3,pfnDriverDetach} */
2079static DECLCALLBACK(int) pdmR3DevHlp_DriverDetach(PPDMDEVINS pDevIns, PPDMDRVINS pDrvIns, uint32_t fFlags)
2080{
2081 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
2082 LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: pDrvIns=%p\n",
2083 pDevIns->pReg->szName, pDevIns->iInstance, pDrvIns));
2084
2085#ifdef VBOX_STRICT
2086 PVM pVM = pDevIns->Internal.s.pVMR3;
2087 VM_ASSERT_EMT(pVM);
2088#endif
2089
2090 int rc = pdmR3DrvDetach(pDrvIns, fFlags);
2091
2092 LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2093 return rc;
2094}
2095
2096
2097/** @interface_method_impl{PDMDEVHLPR3,pfnDriverReconfigure} */
2098static DECLCALLBACK(int) pdmR3DevHlp_DriverReconfigure(PPDMDEVINS pDevIns, uint32_t iLun, uint32_t cDepth,
2099 const char * const *papszDrivers, PCFGMNODE *papConfigs, uint32_t fFlags)
2100{
2101 PDMDEV_ASSERT_DEVINS(pDevIns);
2102 PVM pVM = pDevIns->Internal.s.pVMR3;
2103 VM_ASSERT_EMT(pVM);
2104 LogFlow(("pdmR3DevHlp_DriverReconfigure: caller='%s'/%d: iLun=%u cDepth=%u fFlags=%#x\n",
2105 pDevIns->pReg->szName, pDevIns->iInstance, iLun, cDepth, fFlags));
2106
2107 /*
2108 * Validate input.
2109 */
2110 AssertReturn(cDepth <= 8, VERR_INVALID_PARAMETER);
2111 AssertPtrReturn(papszDrivers, VERR_INVALID_POINTER);
2112 AssertPtrNullReturn(papConfigs, VERR_INVALID_POINTER);
2113 for (uint32_t i = 0; i < cDepth; i++)
2114 {
2115 AssertPtrReturn(papszDrivers[i], VERR_INVALID_POINTER);
2116 size_t cchDriver = strlen(papszDrivers[i]);
2117 AssertPtrReturn(cchDriver > 0 && cchDriver < RT_SIZEOFMEMB(PDMDRVREG, szName), VERR_OUT_OF_RANGE);
2118
2119 if (papConfigs)
2120 AssertPtrNullReturn(papConfigs[i], VERR_INVALID_POINTER);
2121 }
2122 AssertReturn(fFlags == 0, VERR_INVALID_FLAGS);
2123
2124 /*
2125 * Do we have to detach an existing driver first?
2126 */
2127 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
2128 if (pLun->iLun == iLun)
2129 {
2130 if (pLun->pTop)
2131 {
2132 int rc = pdmR3DrvDetach(pLun->pTop, 0);
2133 AssertRCReturn(rc, rc);
2134 }
2135 break;
2136 }
2137
2138 /*
2139 * Remove the old tree.
2140 */
2141 PCFGMNODE pCfgDev = CFGMR3GetChildF(CFGMR3GetRoot(pVM), "Devices/%s/%u/", pDevIns->pReg->szName, pDevIns->iInstance);
2142 AssertReturn(pCfgDev, VERR_INTERNAL_ERROR_2);
2143 PCFGMNODE pCfgLun = CFGMR3GetChildF(pCfgDev, "LUN#%u", iLun);
2144 if (pCfgLun)
2145 CFGMR3RemoveNode(pCfgLun);
2146
2147 /*
2148 * Construct a new tree.
2149 */
2150 int rc = CFGMR3InsertNodeF(pCfgDev, &pCfgLun, "LUN#%u", iLun);
2151 AssertRCReturn(rc, rc);
2152 PCFGMNODE pCfgDrv = pCfgLun;
2153 for (uint32_t i = 0; i < cDepth; i++)
2154 {
2155 rc = CFGMR3InsertString(pCfgDrv, "Driver", papszDrivers[i]);
2156 AssertRCReturn(rc, rc);
2157 if (papConfigs && papConfigs[i])
2158 {
2159 rc = CFGMR3InsertSubTree(pCfgDrv, "Config", papConfigs[i], NULL);
2160 AssertRCReturn(rc, rc);
2161 papConfigs[i] = NULL;
2162 }
2163 else
2164 {
2165 rc = CFGMR3InsertNode(pCfgDrv, "Config", NULL);
2166 AssertRCReturn(rc, rc);
2167 }
2168
2169 if (i + 1 >= cDepth)
2170 break;
2171 rc = CFGMR3InsertNode(pCfgDrv, "AttachedDriver", &pCfgDrv);
2172 AssertRCReturn(rc, rc);
2173 }
2174
2175 LogFlow(("pdmR3DevHlp_DriverReconfigure: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2176 return rc;
2177}
2178
2179
2180/** @interface_method_impl{PDMDEVHLPR3,pfnQueueCreatePtr} */
2181static DECLCALLBACK(int) pdmR3DevHlp_QueueCreatePtr(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
2182 PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue)
2183{
2184 PDMDEV_ASSERT_DEVINS(pDevIns);
2185 LogFlow(("pdmR3DevHlp_QueueCreatePtr: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fRZEnabled=%RTbool pszName=%p:{%s} ppQueue=%p\n",
2186 pDevIns->pReg->szName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, pszName, ppQueue));
2187
2188 PVM pVM = pDevIns->Internal.s.pVMR3;
2189 VM_ASSERT_EMT(pVM);
2190
2191 if (pDevIns->iInstance > 0)
2192 {
2193 pszName = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s_%u", pszName, pDevIns->iInstance);
2194 AssertLogRelReturn(pszName, VERR_NO_MEMORY);
2195 }
2196
2197 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, ppQueue);
2198
2199 LogFlow(("pdmR3DevHlp_QueueCreatePtr: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *ppQueue));
2200 return rc;
2201}
2202
2203
2204/** @interface_method_impl{PDMDEVHLPR3,pfnQueueCreate} */
2205static DECLCALLBACK(int) pdmR3DevHlp_QueueCreate(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
2206 PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName,
2207 PDMQUEUEHANDLE *phQueue)
2208{
2209 PDMDEV_ASSERT_DEVINS(pDevIns);
2210 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fRZEnabled=%RTbool pszName=%p:{%s} phQueue=%p\n",
2211 pDevIns->pReg->szName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, pszName, phQueue));
2212
2213 PVM pVM = pDevIns->Internal.s.pVMR3;
2214 VM_ASSERT_EMT(pVM);
2215
2216 if (pDevIns->iInstance > 0)
2217 {
2218 pszName = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s_%u", pszName, pDevIns->iInstance);
2219 AssertLogRelReturn(pszName, VERR_NO_MEMORY);
2220 }
2221
2222 PPDMQUEUE pQueue = NULL;
2223 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, &pQueue);
2224 *phQueue = (uintptr_t)pQueue;
2225
2226 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phQueue));
2227 return rc;
2228}
2229
2230
2231/** @interface_method_impl{PDMDEVHLPR3,pfnQueueToPtr} */
2232static DECLCALLBACK(PPDMQUEUE) pdmR3DevHlp_QueueToPtr(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
2233{
2234 PDMDEV_ASSERT_DEVINS(pDevIns);
2235 RT_NOREF(pDevIns);
2236 return (PPDMQUEUE)hQueue;
2237}
2238
2239
2240/** @interface_method_impl{PDMDEVHLPR3,pfnQueueAlloc} */
2241static DECLCALLBACK(PPDMQUEUEITEMCORE) pdmR3DevHlp_QueueAlloc(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
2242{
2243 return PDMQueueAlloc(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue));
2244}
2245
2246
2247/** @interface_method_impl{PDMDEVHLPR3,pfnQueueInsert} */
2248static DECLCALLBACK(void) pdmR3DevHlp_QueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)
2249{
2250 return PDMQueueInsert(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue), pItem);
2251}
2252
2253
2254/** @interface_method_impl{PDMDEVHLPR3,pfnQueueInsertEx} */
2255static DECLCALLBACK(void) pdmR3DevHlp_QueueInsertEx(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem,
2256 uint64_t cNanoMaxDelay)
2257{
2258 return PDMQueueInsertEx(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue), pItem, cNanoMaxDelay);
2259}
2260
2261
2262/** @interface_method_impl{PDMDEVHLPR3,pfnQueueFlushIfNecessary} */
2263static DECLCALLBACK(bool) pdmR3DevHlp_QueueFlushIfNecessary(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
2264{
2265 return PDMQueueFlushIfNecessary(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue));
2266}
2267
2268
2269/** @interface_method_impl{PDMDEVHLPR3,pfnTaskCreate} */
2270static DECLCALLBACK(int) pdmR3DevHlp_TaskCreate(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszName,
2271 PFNPDMTASKDEV pfnCallback, void *pvUser, PDMTASKHANDLE *phTask)
2272{
2273 PDMDEV_ASSERT_DEVINS(pDevIns);
2274 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: pfnCallback=%p fFlags=%#x pszName=%p:{%s} phTask=%p\n",
2275 pDevIns->pReg->szName, pDevIns->iInstance, pfnCallback, fFlags, pszName, pszName, phTask));
2276 PVM pVM = pDevIns->Internal.s.pVMR3;
2277 VM_ASSERT_EMT(pVM);
2278
2279 int rc = PDMR3TaskCreate(pVM, fFlags, pszName, PDMTASKTYPE_DEV, pDevIns, (PFNRT)pfnCallback, pvUser, phTask);
2280
2281 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2282 return rc;
2283}
2284
2285
2286/** @interface_method_impl{PDMDEVHLPR3,pfnTaskTrigger} */
2287static DECLCALLBACK(int) pdmR3DevHlp_TaskTrigger(PPDMDEVINS pDevIns, PDMTASKHANDLE hTask)
2288{
2289 PDMDEV_ASSERT_DEVINS(pDevIns);
2290 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: hTask=%RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, hTask));
2291
2292 int rc = PDMTaskTrigger(pDevIns->Internal.s.pVMR3, PDMTASKTYPE_DEV, pDevIns, hTask);
2293
2294 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2295 return rc;
2296}
2297
2298
2299/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventCreate} */
2300static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventCreate(PPDMDEVINS pDevIns, PSUPSEMEVENT phEvent)
2301{
2302 PDMDEV_ASSERT_DEVINS(pDevIns);
2303 LogFlow(("pdmR3DevHlp_SUPSemEventCreate: caller='%s'/%d: phEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, phEvent));
2304 PVM pVM = pDevIns->Internal.s.pVMR3;
2305 VM_ASSERT_EMT(pVM);
2306
2307 int rc = SUPSemEventCreate(pVM->pSession, phEvent);
2308
2309 LogFlow(("pdmR3DevHlp_SUPSemEventCreate: caller='%s'/%d: returns %Rrc *phEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phEvent));
2310 return rc;
2311}
2312
2313
2314/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventClose} */
2315static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventClose(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
2316{
2317 PDMDEV_ASSERT_DEVINS(pDevIns);
2318 LogFlow(("pdmR3DevHlp_SUPSemEventClose: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
2319
2320 int rc = SUPSemEventClose(pDevIns->Internal.s.pVMR3->pSession, hEvent);
2321
2322 LogFlow(("pdmR3DevHlp_SUPSemEventClose: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2323 return rc;
2324}
2325
2326
2327/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventSignal} */
2328static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventSignal(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
2329{
2330 PDMDEV_ASSERT_DEVINS(pDevIns);
2331 LogFlow(("pdmR3DevHlp_SUPSemEventSignal: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
2332
2333 int rc = SUPSemEventSignal(pDevIns->Internal.s.pVMR3->pSession, hEvent);
2334
2335 LogFlow(("pdmR3DevHlp_SUPSemEventSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2336 return rc;
2337}
2338
2339
2340/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNoResume} */
2341static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint32_t cMillies)
2342{
2343 PDMDEV_ASSERT_DEVINS(pDevIns);
2344 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: hEvent=%p cNsTimeout=%RU32\n",
2345 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cMillies));
2346
2347 int rc = SUPSemEventWaitNoResume(pDevIns->Internal.s.pVMR3->pSession, hEvent, cMillies);
2348
2349 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2350 return rc;
2351}
2352
2353
2354/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNsAbsIntr} */
2355static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
2356{
2357 PDMDEV_ASSERT_DEVINS(pDevIns);
2358 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: hEvent=%p uNsTimeout=%RU64\n",
2359 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, uNsTimeout));
2360
2361 int rc = SUPSemEventWaitNsAbsIntr(pDevIns->Internal.s.pVMR3->pSession, hEvent, uNsTimeout);
2362
2363 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2364 return rc;
2365}
2366
2367
2368/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNsRelIntr} */
2369static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
2370{
2371 PDMDEV_ASSERT_DEVINS(pDevIns);
2372 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: hEvent=%p cNsTimeout=%RU64\n",
2373 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cNsTimeout));
2374
2375 int rc = SUPSemEventWaitNsRelIntr(pDevIns->Internal.s.pVMR3->pSession, hEvent, cNsTimeout);
2376
2377 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2378 return rc;
2379}
2380
2381
2382/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventGetResolution} */
2383static DECLCALLBACK(uint32_t) pdmR3DevHlp_SUPSemEventGetResolution(PPDMDEVINS pDevIns)
2384{
2385 PDMDEV_ASSERT_DEVINS(pDevIns);
2386 LogFlow(("pdmR3DevHlp_SUPSemEventGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2387
2388 uint32_t cNsResolution = SUPSemEventGetResolution(pDevIns->Internal.s.pVMR3->pSession);
2389
2390 LogFlow(("pdmR3DevHlp_SUPSemEventGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
2391 return cNsResolution;
2392}
2393
2394
2395/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiCreate} */
2396static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiCreate(PPDMDEVINS pDevIns, PSUPSEMEVENTMULTI phEventMulti)
2397{
2398 PDMDEV_ASSERT_DEVINS(pDevIns);
2399 LogFlow(("pdmR3DevHlp_SUPSemEventMultiCreate: caller='%s'/%d: phEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, phEventMulti));
2400 PVM pVM = pDevIns->Internal.s.pVMR3;
2401 VM_ASSERT_EMT(pVM);
2402
2403 int rc = SUPSemEventMultiCreate(pVM->pSession, phEventMulti);
2404
2405 LogFlow(("pdmR3DevHlp_SUPSemEventMultiCreate: caller='%s'/%d: returns %Rrc *phEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phEventMulti));
2406 return rc;
2407}
2408
2409
2410/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiClose} */
2411static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiClose(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
2412{
2413 PDMDEV_ASSERT_DEVINS(pDevIns);
2414 LogFlow(("pdmR3DevHlp_SUPSemEventMultiClose: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
2415
2416 int rc = SUPSemEventMultiClose(pDevIns->Internal.s.pVMR3->pSession, hEventMulti);
2417
2418 LogFlow(("pdmR3DevHlp_SUPSemEventMultiClose: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2419 return rc;
2420}
2421
2422
2423/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiSignal} */
2424static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiSignal(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
2425{
2426 PDMDEV_ASSERT_DEVINS(pDevIns);
2427 LogFlow(("pdmR3DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
2428
2429 int rc = SUPSemEventMultiSignal(pDevIns->Internal.s.pVMR3->pSession, hEventMulti);
2430
2431 LogFlow(("pdmR3DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2432 return rc;
2433}
2434
2435
2436/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiReset} */
2437static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiReset(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
2438{
2439 PDMDEV_ASSERT_DEVINS(pDevIns);
2440 LogFlow(("pdmR3DevHlp_SUPSemEventMultiReset: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
2441
2442 int rc = SUPSemEventMultiReset(pDevIns->Internal.s.pVMR3->pSession, hEventMulti);
2443
2444 LogFlow(("pdmR3DevHlp_SUPSemEventMultiReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2445 return rc;
2446}
2447
2448
2449/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNoResume} */
2450static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
2451 uint32_t cMillies)
2452{
2453 PDMDEV_ASSERT_DEVINS(pDevIns);
2454 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: hEventMulti=%p cMillies=%RU32\n",
2455 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cMillies));
2456
2457 int rc = SUPSemEventMultiWaitNoResume(pDevIns->Internal.s.pVMR3->pSession, hEventMulti, cMillies);
2458
2459 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2460 return rc;
2461}
2462
2463
2464/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNsAbsIntr} */
2465static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
2466 uint64_t uNsTimeout)
2467{
2468 PDMDEV_ASSERT_DEVINS(pDevIns);
2469 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: hEventMulti=%p uNsTimeout=%RU64\n",
2470 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, uNsTimeout));
2471
2472 int rc = SUPSemEventMultiWaitNsAbsIntr(pDevIns->Internal.s.pVMR3->pSession, hEventMulti, uNsTimeout);
2473
2474 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2475 return rc;
2476}
2477
2478
2479/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNsRelIntr} */
2480static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
2481 uint64_t cNsTimeout)
2482{
2483 PDMDEV_ASSERT_DEVINS(pDevIns);
2484 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: hEventMulti=%p cNsTimeout=%RU64\n",
2485 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cNsTimeout));
2486
2487 int rc = SUPSemEventMultiWaitNsRelIntr(pDevIns->Internal.s.pVMR3->pSession, hEventMulti, cNsTimeout);
2488
2489 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2490 return rc;
2491}
2492
2493
2494/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiGetResolution} */
2495static DECLCALLBACK(uint32_t) pdmR3DevHlp_SUPSemEventMultiGetResolution(PPDMDEVINS pDevIns)
2496{
2497 PDMDEV_ASSERT_DEVINS(pDevIns);
2498 LogFlow(("pdmR3DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2499
2500 uint32_t cNsResolution = SUPSemEventMultiGetResolution(pDevIns->Internal.s.pVMR3->pSession);
2501
2502 LogFlow(("pdmR3DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
2503 return cNsResolution;
2504}
2505
2506
2507/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectInit} */
2508static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
2509 const char *pszNameFmt, va_list va)
2510{
2511 PDMDEV_ASSERT_DEVINS(pDevIns);
2512 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszNameFmt=%p:{%s}\n",
2513 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pszNameFmt, pszNameFmt));
2514
2515 PVM pVM = pDevIns->Internal.s.pVMR3;
2516 VM_ASSERT_EMT(pVM);
2517 int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
2518
2519 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2520 return rc;
2521}
2522
2523
2524/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNop} */
2525static DECLCALLBACK(PPDMCRITSECT) pdmR3DevHlp_CritSectGetNop(PPDMDEVINS pDevIns)
2526{
2527 PDMDEV_ASSERT_DEVINS(pDevIns);
2528 PVM pVM = pDevIns->Internal.s.pVMR3;
2529 VM_ASSERT_EMT(pVM);
2530
2531 PPDMCRITSECT pCritSect = PDMR3CritSectGetNop(pVM);
2532 LogFlow(("pdmR3DevHlp_CritSectGetNop: caller='%s'/%d: return %p\n",
2533 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2534 return pCritSect;
2535}
2536
2537
2538/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopR0} */
2539static DECLCALLBACK(R0PTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopR0(PPDMDEVINS pDevIns)
2540{
2541 PDMDEV_ASSERT_DEVINS(pDevIns);
2542 PVM pVM = pDevIns->Internal.s.pVMR3;
2543 VM_ASSERT_EMT(pVM);
2544
2545 R0PTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopR0(pVM);
2546 LogFlow(("pdmR3DevHlp_CritSectGetNopR0: caller='%s'/%d: return %RHv\n",
2547 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2548 return pCritSect;
2549}
2550
2551
2552/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopRC} */
2553static DECLCALLBACK(RCPTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopRC(PPDMDEVINS pDevIns)
2554{
2555 PDMDEV_ASSERT_DEVINS(pDevIns);
2556 PVM pVM = pDevIns->Internal.s.pVMR3;
2557 VM_ASSERT_EMT(pVM);
2558
2559 RCPTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopRC(pVM);
2560 LogFlow(("pdmR3DevHlp_CritSectGetNopRC: caller='%s'/%d: return %RRv\n",
2561 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2562 return pCritSect;
2563}
2564
2565
2566/** @interface_method_impl{PDMDEVHLPR3,pfnSetDeviceCritSect} */
2567static DECLCALLBACK(int) pdmR3DevHlp_SetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2568{
2569 /*
2570 * Validate input.
2571 *
2572 * Note! We only allow the automatically created default critical section
2573 * to be replaced by this API.
2574 */
2575 PDMDEV_ASSERT_DEVINS(pDevIns);
2576 AssertPtrReturn(pCritSect, VERR_INVALID_POINTER);
2577 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: pCritSect=%p (%s)\n",
2578 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pCritSect->s.pszName));
2579 AssertReturn(PDMCritSectIsInitialized(pCritSect), VERR_INVALID_PARAMETER);
2580 PVM pVM = pDevIns->Internal.s.pVMR3;
2581 AssertReturn(pCritSect->s.pVMR3 == pVM, VERR_INVALID_PARAMETER);
2582
2583 VM_ASSERT_EMT(pVM);
2584 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
2585
2586 AssertReturn(pDevIns->pCritSectRoR3, VERR_PDM_DEV_IPE_1);
2587 AssertReturn(pDevIns->pCritSectRoR3->s.fAutomaticDefaultCritsect, VERR_WRONG_ORDER);
2588 AssertReturn(!pDevIns->pCritSectRoR3->s.fUsedByTimerOrSimilar, VERR_WRONG_ORDER);
2589 AssertReturn(pDevIns->pCritSectRoR3 != pCritSect, VERR_INVALID_PARAMETER);
2590
2591 /*
2592 * Replace the critical section and destroy the automatic default section.
2593 */
2594 PPDMCRITSECT pOldCritSect = pDevIns->pCritSectRoR3;
2595 pDevIns->pCritSectRoR3 = pCritSect;
2596 pDevIns->Internal.s.fIntFlags |= PDMDEVINSINT_FLAGS_CHANGED_CRITSECT;
2597
2598 Assert(RT_BOOL(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED) == pDevIns->fR0Enabled);
2599 if ( (pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED)
2600 && !(pDevIns->Internal.s.pDevR3->pReg->fFlags & PDM_DEVREG_FLAGS_NEW_STYLE))
2601 {
2602 PDMDEVICECOMPATSETCRITSECTREQ Req;
2603 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
2604 Req.Hdr.cbReq = sizeof(Req);
2605 Req.idxR0Device = pDevIns->Internal.s.idxR0Device;
2606 Req.pDevInsR3 = pDevIns;
2607 Req.pCritSectR3 = pCritSect;
2608 int rc = VMMR3CallR0(pVM, VMMR0_DO_PDM_DEVICE_COMPAT_SET_CRITSECT, 0, &Req.Hdr);
2609 AssertLogRelRCReturn(rc, rc);
2610 }
2611
2612 PDMR3CritSectDelete(pOldCritSect);
2613 Assert((uintptr_t)pOldCritSect - (uintptr_t)pDevIns < pDevIns->cbRing3);
2614
2615 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
2616 return VINF_SUCCESS;
2617}
2618
2619
2620/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectYield} */
2621static DECLCALLBACK(bool) pdmR3DevHlp_CritSectYield(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2622{
2623 PDMDEV_ASSERT_DEVINS(pDevIns);
2624 return PDMR3CritSectYield(pDevIns->Internal.s.pVMR3, pCritSect);
2625}
2626
2627
2628/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnter} */
2629static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy)
2630{
2631 PDMDEV_ASSERT_DEVINS(pDevIns);
2632 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2633 return PDMCritSectEnter(pCritSect, rcBusy);
2634}
2635
2636
2637/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnterDebug} */
2638static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
2639{
2640 PDMDEV_ASSERT_DEVINS(pDevIns);
2641 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2642 return PDMCritSectEnterDebug(pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
2643}
2644
2645
2646/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnter} */
2647static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2648{
2649 PDMDEV_ASSERT_DEVINS(pDevIns);
2650 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2651 return PDMCritSectTryEnter(pCritSect);
2652}
2653
2654
2655/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnterDebug} */
2656static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
2657{
2658 PDMDEV_ASSERT_DEVINS(pDevIns);
2659 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2660 return PDMCritSectTryEnterDebug(pCritSect, uId, RT_SRC_POS_ARGS);
2661}
2662
2663
2664/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectLeave} */
2665static DECLCALLBACK(int) pdmR3DevHlp_CritSectLeave(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2666{
2667 PDMDEV_ASSERT_DEVINS(pDevIns);
2668 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2669 return PDMCritSectLeave(pCritSect);
2670}
2671
2672
2673/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsOwner} */
2674static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsOwner(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2675{
2676 PDMDEV_ASSERT_DEVINS(pDevIns);
2677 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2678 return PDMCritSectIsOwner(pCritSect);
2679}
2680
2681
2682/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsInitialized} */
2683static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsInitialized(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2684{
2685 PDMDEV_ASSERT_DEVINS(pDevIns);
2686 RT_NOREF(pDevIns);
2687 return PDMCritSectIsInitialized(pCritSect);
2688}
2689
2690
2691/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectHasWaiters} */
2692static DECLCALLBACK(bool) pdmR3DevHlp_CritSectHasWaiters(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2693{
2694 PDMDEV_ASSERT_DEVINS(pDevIns);
2695 RT_NOREF(pDevIns);
2696 return PDMCritSectHasWaiters(pCritSect);
2697}
2698
2699
2700/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetRecursion} */
2701static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectGetRecursion(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2702{
2703 PDMDEV_ASSERT_DEVINS(pDevIns);
2704 RT_NOREF(pDevIns);
2705 return PDMCritSectGetRecursion(pCritSect);
2706}
2707
2708
2709/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectScheduleExitEvent} */
2710static DECLCALLBACK(int) pdmR3DevHlp_CritSectScheduleExitEvent(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect,
2711 SUPSEMEVENT hEventToSignal)
2712{
2713 PDMDEV_ASSERT_DEVINS(pDevIns);
2714 RT_NOREF(pDevIns);
2715 return PDMHCCritSectScheduleExitEvent(pCritSect, hEventToSignal);
2716}
2717
2718
2719/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectDelete} */
2720static DECLCALLBACK(int) pdmR3DevHlp_CritSectDelete(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2721{
2722 PDMDEV_ASSERT_DEVINS(pDevIns);
2723 RT_NOREF(pDevIns);
2724 return PDMR3CritSectDelete(pCritSect);
2725}
2726
2727
2728/** @interface_method_impl{PDMDEVHLPR3,pfnThreadCreate} */
2729static DECLCALLBACK(int) pdmR3DevHlp_ThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
2730 PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
2731{
2732 PDMDEV_ASSERT_DEVINS(pDevIns);
2733 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2734 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
2735 pDevIns->pReg->szName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
2736
2737 int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
2738
2739 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDevIns->pReg->szName, pDevIns->iInstance,
2740 rc, *ppThread));
2741 return rc;
2742}
2743
2744
2745/** @interface_method_impl{PDMDEVHLPR3,pfnSetAsyncNotification} */
2746static DECLCALLBACK(int) pdmR3DevHlp_SetAsyncNotification(PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)
2747{
2748 PDMDEV_ASSERT_DEVINS(pDevIns);
2749 VM_ASSERT_EMT0(pDevIns->Internal.s.pVMR3);
2750 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: pfnAsyncNotify=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pfnAsyncNotify));
2751
2752 int rc = VINF_SUCCESS;
2753 AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
2754 AssertStmt(!pDevIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
2755 AssertStmt(pDevIns->Internal.s.fIntFlags & (PDMDEVINSINT_FLAGS_SUSPENDED | PDMDEVINSINT_FLAGS_RESET), rc = VERR_WRONG_ORDER);
2756 VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
2757 AssertStmt( enmVMState == VMSTATE_SUSPENDING
2758 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
2759 || enmVMState == VMSTATE_SUSPENDING_LS
2760 || enmVMState == VMSTATE_RESETTING
2761 || enmVMState == VMSTATE_RESETTING_LS
2762 || enmVMState == VMSTATE_POWERING_OFF
2763 || enmVMState == VMSTATE_POWERING_OFF_LS,
2764 rc = VERR_INVALID_STATE);
2765
2766 if (RT_SUCCESS(rc))
2767 pDevIns->Internal.s.pfnAsyncNotify = pfnAsyncNotify;
2768
2769 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2770 return rc;
2771}
2772
2773
2774/** @interface_method_impl{PDMDEVHLPR3,pfnAsyncNotificationCompleted} */
2775static DECLCALLBACK(void) pdmR3DevHlp_AsyncNotificationCompleted(PPDMDEVINS pDevIns)
2776{
2777 PDMDEV_ASSERT_DEVINS(pDevIns);
2778 PVM pVM = pDevIns->Internal.s.pVMR3;
2779
2780 VMSTATE enmVMState = VMR3GetState(pVM);
2781 if ( enmVMState == VMSTATE_SUSPENDING
2782 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
2783 || enmVMState == VMSTATE_SUSPENDING_LS
2784 || enmVMState == VMSTATE_RESETTING
2785 || enmVMState == VMSTATE_RESETTING_LS
2786 || enmVMState == VMSTATE_POWERING_OFF
2787 || enmVMState == VMSTATE_POWERING_OFF_LS)
2788 {
2789 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2790 VMR3AsyncPdmNotificationWakeupU(pVM->pUVM);
2791 }
2792 else
2793 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d: enmVMState=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, enmVMState));
2794}
2795
2796
2797/** @interface_method_impl{PDMDEVHLPR3,pfnRTCRegister} */
2798static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
2799{
2800 PDMDEV_ASSERT_DEVINS(pDevIns);
2801 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2802 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
2803 pDevIns->pReg->szName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
2804 pRtcReg->pfnWrite, ppRtcHlp));
2805
2806 /*
2807 * Validate input.
2808 */
2809 if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
2810 {
2811 AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
2812 PDM_RTCREG_VERSION));
2813 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (version)\n",
2814 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2815 return VERR_INVALID_PARAMETER;
2816 }
2817 if ( !pRtcReg->pfnWrite
2818 || !pRtcReg->pfnRead)
2819 {
2820 Assert(pRtcReg->pfnWrite);
2821 Assert(pRtcReg->pfnRead);
2822 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
2823 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2824 return VERR_INVALID_PARAMETER;
2825 }
2826
2827 if (!ppRtcHlp)
2828 {
2829 Assert(ppRtcHlp);
2830 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (ppRtcHlp)\n",
2831 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2832 return VERR_INVALID_PARAMETER;
2833 }
2834
2835 /*
2836 * Only one DMA device.
2837 */
2838 PVM pVM = pDevIns->Internal.s.pVMR3;
2839 if (pVM->pdm.s.pRtc)
2840 {
2841 AssertMsgFailed(("Only one RTC device is supported!\n"));
2842 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
2843 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2844 return VERR_INVALID_PARAMETER;
2845 }
2846
2847 /*
2848 * Allocate and initialize pci bus structure.
2849 */
2850 int rc = VINF_SUCCESS;
2851 PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
2852 if (pRtc)
2853 {
2854 pRtc->pDevIns = pDevIns;
2855 pRtc->Reg = *pRtcReg;
2856 pVM->pdm.s.pRtc = pRtc;
2857
2858 /* set the helper pointer. */
2859 *ppRtcHlp = &g_pdmR3DevRtcHlp;
2860 Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
2861 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
2862 }
2863 else
2864 rc = VERR_NO_MEMORY;
2865
2866 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
2867 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2868 return rc;
2869}
2870
2871
2872/** @interface_method_impl{PDMDEVHLPR3,pfnDMARegister} */
2873static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
2874{
2875 PDMDEV_ASSERT_DEVINS(pDevIns);
2876 PVM pVM = pDevIns->Internal.s.pVMR3;
2877 VM_ASSERT_EMT(pVM);
2878 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
2879 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
2880 int rc = VINF_SUCCESS;
2881 if (pVM->pdm.s.pDmac)
2882 pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
2883 else
2884 {
2885 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2886 rc = VERR_PDM_NO_DMAC_INSTANCE;
2887 }
2888 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Rrc\n",
2889 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2890 return rc;
2891}
2892
2893
2894/** @interface_method_impl{PDMDEVHLPR3,pfnDMAReadMemory} */
2895static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
2896{
2897 PDMDEV_ASSERT_DEVINS(pDevIns);
2898 PVM pVM = pDevIns->Internal.s.pVMR3;
2899 VM_ASSERT_EMT(pVM);
2900 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
2901 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
2902 int rc = VINF_SUCCESS;
2903 if (pVM->pdm.s.pDmac)
2904 {
2905 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
2906 if (pcbRead)
2907 *pcbRead = cb;
2908 }
2909 else
2910 {
2911 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2912 rc = VERR_PDM_NO_DMAC_INSTANCE;
2913 }
2914 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Rrc\n",
2915 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2916 return rc;
2917}
2918
2919
2920/** @interface_method_impl{PDMDEVHLPR3,pfnDMAWriteMemory} */
2921static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
2922{
2923 PDMDEV_ASSERT_DEVINS(pDevIns);
2924 PVM pVM = pDevIns->Internal.s.pVMR3;
2925 VM_ASSERT_EMT(pVM);
2926 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
2927 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
2928 int rc = VINF_SUCCESS;
2929 if (pVM->pdm.s.pDmac)
2930 {
2931 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
2932 if (pcbWritten)
2933 *pcbWritten = cb;
2934 }
2935 else
2936 {
2937 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2938 rc = VERR_PDM_NO_DMAC_INSTANCE;
2939 }
2940 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Rrc\n",
2941 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2942 return rc;
2943}
2944
2945
2946/** @interface_method_impl{PDMDEVHLPR3,pfnDMASetDREQ} */
2947static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
2948{
2949 PDMDEV_ASSERT_DEVINS(pDevIns);
2950 PVM pVM = pDevIns->Internal.s.pVMR3;
2951 VM_ASSERT_EMT(pVM);
2952 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
2953 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, uLevel));
2954 int rc = VINF_SUCCESS;
2955 if (pVM->pdm.s.pDmac)
2956 pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
2957 else
2958 {
2959 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2960 rc = VERR_PDM_NO_DMAC_INSTANCE;
2961 }
2962 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Rrc\n",
2963 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2964 return rc;
2965}
2966
2967/** @interface_method_impl{PDMDEVHLPR3,pfnDMAGetChannelMode} */
2968static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
2969{
2970 PDMDEV_ASSERT_DEVINS(pDevIns);
2971 PVM pVM = pDevIns->Internal.s.pVMR3;
2972 VM_ASSERT_EMT(pVM);
2973 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
2974 pDevIns->pReg->szName, pDevIns->iInstance, uChannel));
2975 uint8_t u8Mode;
2976 if (pVM->pdm.s.pDmac)
2977 u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
2978 else
2979 {
2980 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2981 u8Mode = 3 << 2 /* illegal mode type */;
2982 }
2983 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
2984 pDevIns->pReg->szName, pDevIns->iInstance, u8Mode));
2985 return u8Mode;
2986}
2987
2988/** @interface_method_impl{PDMDEVHLPR3,pfnDMASchedule} */
2989static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
2990{
2991 PDMDEV_ASSERT_DEVINS(pDevIns);
2992 PVM pVM = pDevIns->Internal.s.pVMR3;
2993 VM_ASSERT_EMT(pVM);
2994 LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
2995 pDevIns->pReg->szName, pDevIns->iInstance, VM_FF_IS_SET(pVM, VM_FF_PDM_DMA)));
2996
2997 AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2998 VM_FF_SET(pVM, VM_FF_PDM_DMA);
2999 VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
3000}
3001
3002
3003/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSWrite} */
3004static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
3005{
3006 PDMDEV_ASSERT_DEVINS(pDevIns);
3007 PVM pVM = pDevIns->Internal.s.pVMR3;
3008 VM_ASSERT_EMT(pVM);
3009
3010 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
3011 pDevIns->pReg->szName, pDevIns->iInstance, iReg, u8Value));
3012 int rc;
3013 if (pVM->pdm.s.pRtc)
3014 {
3015 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
3016 rc = PDMCritSectEnter(pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
3017 if (RT_SUCCESS(rc))
3018 {
3019 rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pDevInsRtc, iReg, u8Value);
3020 PDMCritSectLeave(pDevInsRtc->pCritSectRoR3);
3021 }
3022 }
3023 else
3024 rc = VERR_PDM_NO_RTC_INSTANCE;
3025
3026 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
3027 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3028 return rc;
3029}
3030
3031
3032/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSRead} */
3033static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
3034{
3035 PDMDEV_ASSERT_DEVINS(pDevIns);
3036 PVM pVM = pDevIns->Internal.s.pVMR3;
3037 VM_ASSERT_EMT(pVM);
3038
3039 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
3040 pDevIns->pReg->szName, pDevIns->iInstance, iReg, pu8Value));
3041 int rc;
3042 if (pVM->pdm.s.pRtc)
3043 {
3044 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
3045 rc = PDMCritSectEnter(pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
3046 if (RT_SUCCESS(rc))
3047 {
3048 rc = pVM->pdm.s.pRtc->Reg.pfnRead(pDevInsRtc, iReg, pu8Value);
3049 PDMCritSectLeave(pDevInsRtc->pCritSectRoR3);
3050 }
3051 }
3052 else
3053 rc = VERR_PDM_NO_RTC_INSTANCE;
3054
3055 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
3056 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3057 return rc;
3058}
3059
3060
3061/** @interface_method_impl{PDMDEVHLPR3,pfnAssertEMT} */
3062static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3063{
3064 PDMDEV_ASSERT_DEVINS(pDevIns);
3065 if (VM_IS_EMT(pDevIns->Internal.s.pVMR3))
3066 return true;
3067
3068 char szMsg[100];
3069 RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
3070 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
3071 AssertBreakpoint();
3072 return false;
3073}
3074
3075
3076/** @interface_method_impl{PDMDEVHLPR3,pfnAssertOther} */
3077static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3078{
3079 PDMDEV_ASSERT_DEVINS(pDevIns);
3080 if (!VM_IS_EMT(pDevIns->Internal.s.pVMR3))
3081 return true;
3082
3083 char szMsg[100];
3084 RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
3085 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
3086 AssertBreakpoint();
3087 return false;
3088}
3089
3090
3091/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetRCInterfaceSymbols} */
3092static DECLCALLBACK(int) pdmR3DevHlp_LdrGetRCInterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
3093 const char *pszSymPrefix, const char *pszSymList)
3094{
3095 PDMDEV_ASSERT_DEVINS(pDevIns);
3096 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3097 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
3098 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
3099
3100 int rc;
3101 if ( strncmp(pszSymPrefix, "dev", 3) == 0
3102 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
3103 {
3104 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
3105 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
3106 pvInterface, cbInterface,
3107 pDevIns->pReg->pszRCMod, pDevIns->Internal.s.pDevR3->pszRCSearchPath,
3108 pszSymPrefix, pszSymList,
3109 false /*fRing0OrRC*/);
3110 else
3111 {
3112 AssertMsgFailed(("Not a raw-mode enabled driver\n"));
3113 rc = VERR_PERMISSION_DENIED;
3114 }
3115 }
3116 else
3117 {
3118 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
3119 pszSymPrefix, pDevIns->pReg->szName));
3120 rc = VERR_INVALID_NAME;
3121 }
3122
3123 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3124 pDevIns->iInstance, rc));
3125 return rc;
3126}
3127
3128
3129/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetR0InterfaceSymbols} */
3130static DECLCALLBACK(int) pdmR3DevHlp_LdrGetR0InterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
3131 const char *pszSymPrefix, const char *pszSymList)
3132{
3133 PDMDEV_ASSERT_DEVINS(pDevIns);
3134 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3135 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
3136 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
3137
3138 int rc;
3139 if ( strncmp(pszSymPrefix, "dev", 3) == 0
3140 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
3141 {
3142 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3143 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
3144 pvInterface, cbInterface,
3145 pDevIns->pReg->pszR0Mod, pDevIns->Internal.s.pDevR3->pszR0SearchPath,
3146 pszSymPrefix, pszSymList,
3147 true /*fRing0OrRC*/);
3148 else
3149 {
3150 AssertMsgFailed(("Not a ring-0 enabled driver\n"));
3151 rc = VERR_PERMISSION_DENIED;
3152 }
3153 }
3154 else
3155 {
3156 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
3157 pszSymPrefix, pDevIns->pReg->szName));
3158 rc = VERR_INVALID_NAME;
3159 }
3160
3161 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3162 pDevIns->iInstance, rc));
3163 return rc;
3164}
3165
3166
3167/** @interface_method_impl{PDMDEVHLPR3,pfnCallR0} */
3168static DECLCALLBACK(int) pdmR3DevHlp_CallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
3169{
3170 PDMDEV_ASSERT_DEVINS(pDevIns);
3171 PVM pVM = pDevIns->Internal.s.pVMR3;
3172 PVMCPU pVCpu = VMMGetCpu(pVM);
3173 AssertReturn(pVCpu, VERR_VM_THREAD_IS_EMT);
3174 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: uOperation=%#x u64Arg=%#RX64\n",
3175 pDevIns->pReg->szName, pDevIns->iInstance, uOperation, u64Arg));
3176
3177 /*
3178 * Resolve the ring-0 entry point. There is not need to remember this like
3179 * we do for drivers since this is mainly for construction time hacks and
3180 * other things that aren't performance critical.
3181 */
3182 int rc;
3183 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3184 {
3185 /*
3186 * Make the ring-0 call.
3187 */
3188 PDMDEVICEGENCALLREQ Req;
3189 RT_ZERO(Req.Params);
3190 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
3191 Req.Hdr.cbReq = sizeof(Req);
3192 Req.pDevInsR3 = pDevIns;
3193 Req.idxR0Device = pDevIns->Internal.s.idxR0Device;
3194 Req.enmCall = PDMDEVICEGENCALL_REQUEST;
3195 Req.Params.Req.uReq = uOperation;
3196 Req.Params.Req.uArg = u64Arg;
3197 rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_PDM_DEVICE_GEN_CALL, 0, &Req.Hdr);
3198 }
3199 else
3200 rc = VERR_ACCESS_DENIED;
3201 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3202 pDevIns->iInstance, rc));
3203 return rc;
3204}
3205
3206
3207/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetSuspendReason} */
3208static DECLCALLBACK(VMSUSPENDREASON) pdmR3DevHlp_VMGetSuspendReason(PPDMDEVINS pDevIns)
3209{
3210 PDMDEV_ASSERT_DEVINS(pDevIns);
3211 PVM pVM = pDevIns->Internal.s.pVMR3;
3212 VM_ASSERT_EMT(pVM);
3213 VMSUSPENDREASON enmReason = VMR3GetSuspendReason(pVM->pUVM);
3214 LogFlow(("pdmR3DevHlp_VMGetSuspendReason: caller='%s'/%d: returns %d\n",
3215 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3216 return enmReason;
3217}
3218
3219
3220/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetResumeReason} */
3221static DECLCALLBACK(VMRESUMEREASON) pdmR3DevHlp_VMGetResumeReason(PPDMDEVINS pDevIns)
3222{
3223 PDMDEV_ASSERT_DEVINS(pDevIns);
3224 PVM pVM = pDevIns->Internal.s.pVMR3;
3225 VM_ASSERT_EMT(pVM);
3226 VMRESUMEREASON enmReason = VMR3GetResumeReason(pVM->pUVM);
3227 LogFlow(("pdmR3DevHlp_VMGetResumeReason: caller='%s'/%d: returns %d\n",
3228 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3229 return enmReason;
3230}
3231
3232
3233/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
3234static DECLCALLBACK(PUVM) pdmR3DevHlp_GetUVM(PPDMDEVINS pDevIns)
3235{
3236 PDMDEV_ASSERT_DEVINS(pDevIns);
3237 LogFlow(("pdmR3DevHlp_GetUVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3238 return pDevIns->Internal.s.pVMR3->pUVM;
3239}
3240
3241
3242/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
3243static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
3244{
3245 PDMDEV_ASSERT_DEVINS(pDevIns);
3246 LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3247 return pDevIns->Internal.s.pVMR3;
3248}
3249
3250
3251/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
3252static DECLCALLBACK(PVMCPU) pdmR3DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
3253{
3254 PDMDEV_ASSERT_DEVINS(pDevIns);
3255 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3256 LogFlow(("pdmR3DevHlp_GetVMCPU: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, VMMGetCpuId(pDevIns->Internal.s.pVMR3)));
3257 return VMMGetCpu(pDevIns->Internal.s.pVMR3);
3258}
3259
3260
3261/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
3262static DECLCALLBACK(VMCPUID) pdmR3DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
3263{
3264 PDMDEV_ASSERT_DEVINS(pDevIns);
3265 VMCPUID idCpu = VMMGetCpuId(pDevIns->Internal.s.pVMR3);
3266 LogFlow(("pdmR3DevHlp_GetCurrentCpuId: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, idCpu));
3267 return idCpu;
3268}
3269
3270
3271/** @interface_method_impl{PDMDEVHLPR3,pfnPCIBusRegister} */
3272static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREGR3 pPciBusReg,
3273 PCPDMPCIHLPR3 *ppPciHlp, uint32_t *piBus)
3274{
3275 PDMDEV_ASSERT_DEVINS(pDevIns);
3276 PVM pVM = pDevIns->Internal.s.pVMR3;
3277 VM_ASSERT_EMT(pVM);
3278 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, "
3279 ".pfnInterceptConfigAccesses=%p, pfnConfigRead=%p, pfnConfigWrite=%p, .pfnSetIrqR3=%p, .u32EndVersion=%#x} ppPciHlpR3=%p piBus=%p\n",
3280 pDevIns->pReg->szName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
3281 pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnInterceptConfigAccesses, pPciBusReg->pfnConfigRead,
3282 pPciBusReg->pfnConfigWrite, pPciBusReg->pfnSetIrqR3, pPciBusReg->u32EndVersion, ppPciHlp, piBus));
3283
3284 /*
3285 * Validate the structure and output parameters.
3286 */
3287 AssertLogRelMsgReturn(pPciBusReg->u32Version == PDM_PCIBUSREGR3_VERSION,
3288 ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
3289 VERR_INVALID_PARAMETER);
3290 AssertPtrReturn(pPciBusReg->pfnRegisterR3, VERR_INVALID_PARAMETER);
3291 AssertPtrNullReturn(pPciBusReg->pfnRegisterMsiR3, VERR_INVALID_POINTER);
3292 AssertPtrReturn(pPciBusReg->pfnIORegionRegisterR3, VERR_INVALID_POINTER);
3293 AssertPtrReturn(pPciBusReg->pfnInterceptConfigAccesses, VERR_INVALID_POINTER);
3294 AssertPtrReturn(pPciBusReg->pfnConfigWrite, VERR_INVALID_POINTER);
3295 AssertPtrReturn(pPciBusReg->pfnConfigRead, VERR_INVALID_POINTER);
3296 AssertPtrReturn(pPciBusReg->pfnSetIrqR3, VERR_INVALID_POINTER);
3297 AssertLogRelMsgReturn(pPciBusReg->u32EndVersion == PDM_PCIBUSREGR3_VERSION,
3298 ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
3299 VERR_INVALID_PARAMETER);
3300 AssertPtrReturn(ppPciHlp, VERR_INVALID_POINTER);
3301 AssertPtrNullReturn(piBus, VERR_INVALID_POINTER);
3302 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3303
3304 /*
3305 * Find free PCI bus entry.
3306 */
3307 unsigned iBus = 0;
3308 for (iBus = 0; iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
3309 if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
3310 break;
3311 AssertLogRelMsgReturn(iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses),
3312 ("Too many PCI buses. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aPciBuses)),
3313 VERR_OUT_OF_RESOURCES);
3314 PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
3315
3316 /*
3317 * Init the R3 bits.
3318 */
3319 pPciBus->iBus = iBus;
3320 pPciBus->pDevInsR3 = pDevIns;
3321 pPciBus->pfnRegister = pPciBusReg->pfnRegisterR3;
3322 pPciBus->pfnRegisterMsi = pPciBusReg->pfnRegisterMsiR3;
3323 pPciBus->pfnIORegionRegister = pPciBusReg->pfnIORegionRegisterR3;
3324 pPciBus->pfnInterceptConfigAccesses = pPciBusReg->pfnInterceptConfigAccesses;
3325 pPciBus->pfnConfigRead = pPciBusReg->pfnConfigRead;
3326 pPciBus->pfnConfigWrite = pPciBusReg->pfnConfigWrite;
3327 pPciBus->pfnSetIrqR3 = pPciBusReg->pfnSetIrqR3;
3328
3329 Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3330
3331 /* set the helper pointer and return. */
3332 *ppPciHlp = &g_pdmR3DevPciHlp;
3333 if (piBus)
3334 *piBus = iBus;
3335 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc *piBus=%u\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS, iBus));
3336 return VINF_SUCCESS;
3337}
3338
3339
3340/** @interface_method_impl{PDMDEVHLPR3,pfnIommuRegister} */
3341static DECLCALLBACK(int) pdmR3DevHlp_IommuRegister(PPDMDEVINS pDevIns, PPDMIOMMUREGR3 pIommuReg, PCPDMIOMMUHLPR3 *ppIommuHlp,
3342 uint32_t *pidxIommu)
3343{
3344 PDMDEV_ASSERT_DEVINS(pDevIns);
3345 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3346 LogFlow(("pdmR3DevHlp_IommuRegister: caller='%s'/%d: pIommuReg=%p:{.u32Version=%#x, .u32TheEnd=%#x } ppIommuHlp=%p\n",
3347 pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg, pIommuReg->u32Version, pIommuReg->u32TheEnd, ppIommuHlp));
3348 PVM pVM = pDevIns->Internal.s.pVMR3;
3349
3350 /*
3351 * Validate input.
3352 */
3353 AssertMsgReturn(pIommuReg->u32Version == PDM_IOMMUREGR3_VERSION,
3354 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg->u32Version, PDM_IOMMUREGR3_VERSION),
3355 VERR_INVALID_PARAMETER);
3356 AssertPtrReturn(pIommuReg->pfnMemRead, VERR_INVALID_POINTER);
3357 AssertPtrReturn(pIommuReg->pfnMemWrite, VERR_INVALID_POINTER);
3358 AssertPtrReturn(pIommuReg->pfnMsiRemap, VERR_INVALID_POINTER);
3359 AssertMsgReturn(pIommuReg->u32TheEnd == PDM_IOMMUREGR3_VERSION,
3360 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg->u32TheEnd, PDM_IOMMUREGR3_VERSION),
3361 VERR_INVALID_PARAMETER);
3362 AssertPtrReturn(ppIommuHlp, VERR_INVALID_POINTER);
3363
3364 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3365 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3366
3367 /*
3368 * Find free IOMMU slot.
3369 * The IOMMU at the root complex is the one at 0.
3370 */
3371 unsigned idxIommu = 0;
3372#if 0
3373 for (idxIommu = 0; idxIommu < RT_ELEMENTS(pVM->pdm.s.aIommus); idxIommu++)
3374 if (!pVM->pdm.s.aIommus[idxIommu].pDevInsR3)
3375 break;
3376 AssertLogRelMsgReturn(idxIommu < RT_ELEMENTS(pVM->pdm.s.aIommus),
3377 ("Too many IOMMUs. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aIommus)),
3378 VERR_OUT_OF_RESOURCES);
3379#else
3380 /* Currently we support only a single IOMMU. */
3381 AssertMsgReturn(!pVM->pdm.s.aIommus[0].pDevInsR3,
3382 ("%s/%u: Only one IOMMU device is supported!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3383 VERR_ALREADY_EXISTS);
3384#endif
3385 PPDMIOMMU pIommu = &pVM->pdm.s.aIommus[idxIommu];
3386
3387 /*
3388 * Init the R3 bits.
3389 */
3390 pIommu->idxIommu = idxIommu;
3391 pIommu->pDevInsR3 = pDevIns;
3392 pIommu->pfnMemRead = pIommuReg->pfnMemRead;
3393 pIommu->pfnMemWrite = pIommuReg->pfnMemWrite;
3394 pIommu->pfnMsiRemap = pIommuReg->pfnMsiRemap;
3395 Log(("PDM: Registered IOMMU device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3396
3397 /* Set the helper pointer and return. */
3398 *ppIommuHlp = &g_pdmR3DevIommuHlp;
3399 if (pidxIommu)
3400 *pidxIommu = idxIommu;
3401 LogFlow(("pdmR3DevHlp_IommuRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3402 return VINF_SUCCESS;
3403}
3404
3405
3406
3407/** @interface_method_impl{PDMDEVHLPR3,pfnPICRegister} */
3408static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp)
3409{
3410 PDMDEV_ASSERT_DEVINS(pDevIns);
3411 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3412 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnGetInterrupt=%p, .u32TheEnd=%#x } ppPicHlp=%p\n",
3413 pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrq, pPicReg->pfnGetInterrupt, pPicReg->u32TheEnd, ppPicHlp));
3414 PVM pVM = pDevIns->Internal.s.pVMR3;
3415
3416 /*
3417 * Validate input.
3418 */
3419 AssertMsgReturn(pPicReg->u32Version == PDM_PICREG_VERSION,
3420 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32Version, PDM_PICREG_VERSION),
3421 VERR_INVALID_PARAMETER);
3422 AssertPtrReturn(pPicReg->pfnSetIrq, VERR_INVALID_POINTER);
3423 AssertPtrReturn(pPicReg->pfnGetInterrupt, VERR_INVALID_POINTER);
3424 AssertMsgReturn(pPicReg->u32TheEnd == PDM_PICREG_VERSION,
3425 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32TheEnd, PDM_PICREG_VERSION),
3426 VERR_INVALID_PARAMETER);
3427 AssertPtrReturn(ppPicHlp, VERR_INVALID_POINTER);
3428
3429 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3430 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3431
3432 /*
3433 * Only one PIC device.
3434 */
3435 AssertMsgReturn(pVM->pdm.s.Pic.pDevInsR3 == NULL, ("%s/%d: Only one PIC!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3436 VERR_ALREADY_EXISTS);
3437
3438 /*
3439 * Take down the callbacks and instance.
3440 */
3441 pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
3442 pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrq;
3443 pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterrupt;
3444 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3445
3446 /* set the helper pointer and return. */
3447 *ppPicHlp = &g_pdmR3DevPicHlp;
3448 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3449 return VINF_SUCCESS;
3450}
3451
3452
3453/** @interface_method_impl{PDMDEVHLPR3,pfnApicRegister} */
3454static DECLCALLBACK(int) pdmR3DevHlp_ApicRegister(PPDMDEVINS pDevIns)
3455{
3456 PDMDEV_ASSERT_DEVINS(pDevIns);
3457
3458 /*
3459 * Validate caller context.
3460 */
3461 PVM pVM = pDevIns->Internal.s.pVMR3;
3462 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3463 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3464
3465 /*
3466 * Only one APIC device. On SMP we have single logical device covering all LAPICs,
3467 * as they need to communicate and share state easily.
3468 */
3469 AssertMsgReturn(pVM->pdm.s.Apic.pDevInsR3 == NULL,
3470 ("%s/%u: Only one APIC device is supported!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3471 VERR_ALREADY_EXISTS);
3472
3473 /*
3474 * Set the ring-3 and raw-mode bits, leave the ring-0 to ring-0 setup.
3475 */
3476 pVM->pdm.s.Apic.pDevInsR3 = pDevIns;
3477 pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3478 Assert(pVM->pdm.s.Apic.pDevInsRC || !VM_IS_RAW_MODE_ENABLED(pVM));
3479
3480 LogFlow(("pdmR3DevHlp_ApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3481 return VINF_SUCCESS;
3482}
3483
3484
3485/** @interface_method_impl{PDMDEVHLPR3,pfnIoApicRegister} */
3486static DECLCALLBACK(int) pdmR3DevHlp_IoApicRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
3487{
3488 PDMDEV_ASSERT_DEVINS(pDevIns);
3489 LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnSendMsi=%p, .pfnSetEoi=%p, .u32TheEnd=%#x } ppIoApicHlp=%p\n",
3490 pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrq, pIoApicReg->pfnSendMsi, pIoApicReg->pfnSetEoi, pIoApicReg->u32TheEnd, ppIoApicHlp));
3491 PVM pVM = pDevIns->Internal.s.pVMR3;
3492
3493 /*
3494 * Validate input.
3495 */
3496 AssertMsgReturn(pIoApicReg->u32Version == PDM_IOAPICREG_VERSION,
3497 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32Version, PDM_IOAPICREG_VERSION),
3498 VERR_VERSION_MISMATCH);
3499 AssertPtrReturn(pIoApicReg->pfnSetIrq, VERR_INVALID_POINTER);
3500 AssertPtrReturn(pIoApicReg->pfnSendMsi, VERR_INVALID_POINTER);
3501 AssertPtrReturn(pIoApicReg->pfnSetEoi, VERR_INVALID_POINTER);
3502 AssertMsgReturn(pIoApicReg->u32TheEnd == PDM_IOAPICREG_VERSION,
3503 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32TheEnd, PDM_IOAPICREG_VERSION),
3504 VERR_VERSION_MISMATCH);
3505 AssertPtrReturn(ppIoApicHlp, VERR_INVALID_POINTER);
3506 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3507 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3508
3509 /*
3510 * The I/O APIC requires the APIC to be present (hacks++).
3511 * If the I/O APIC does GC stuff so must the APIC.
3512 */
3513 AssertMsgReturn(pVM->pdm.s.Apic.pDevInsR3 != NULL, ("Configuration error / Init order error! No APIC!\n"), VERR_WRONG_ORDER);
3514
3515 /*
3516 * Only one I/O APIC device.
3517 */
3518 AssertMsgReturn(pVM->pdm.s.IoApic.pDevInsR3 == NULL,
3519 ("Only one IOAPIC device is supported! (caller %s/%d)\n", pDevIns->pReg->szName, pDevIns->iInstance),
3520 VERR_ALREADY_EXISTS);
3521
3522 /*
3523 * Initialize the R3 bits.
3524 */
3525 pVM->pdm.s.IoApic.pDevInsR3 = pDevIns;
3526 pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrq;
3527 pVM->pdm.s.IoApic.pfnSendMsiR3 = pIoApicReg->pfnSendMsi;
3528 pVM->pdm.s.IoApic.pfnSetEoiR3 = pIoApicReg->pfnSetEoi;
3529 Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3530
3531 /* set the helper pointer and return. */
3532 *ppIoApicHlp = &g_pdmR3DevIoApicHlp;
3533 LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3534 return VINF_SUCCESS;
3535}
3536
3537
3538/** @interface_method_impl{PDMDEVHLPR3,pfnHpetRegister} */
3539static DECLCALLBACK(int) pdmR3DevHlp_HpetRegister(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3)
3540{
3541 PDMDEV_ASSERT_DEVINS(pDevIns);
3542 LogFlow(("pdmR3DevHlp_HpetRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3543 PVM pVM = pDevIns->Internal.s.pVMR3;
3544
3545 /*
3546 * Validate input.
3547 */
3548 AssertMsgReturn(pHpetReg->u32Version == PDM_HPETREG_VERSION,
3549 ("%s/%u: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pHpetReg->u32Version, PDM_HPETREG_VERSION),
3550 VERR_VERSION_MISMATCH);
3551 AssertPtrReturn(ppHpetHlpR3, VERR_INVALID_POINTER);
3552 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3553 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3554
3555 /*
3556 * Only one HPET device.
3557 */
3558 AssertMsgReturn(pVM->pdm.s.pHpet == NULL,
3559 ("Only one HPET device is supported! (caller %s/%d)\n", pDevIns->pReg->szName, pDevIns->iInstance),
3560 VERR_ALREADY_EXISTS);
3561
3562 /*
3563 * Do the job (what there is of it).
3564 */
3565 pVM->pdm.s.pHpet = pDevIns;
3566 *ppHpetHlpR3 = &g_pdmR3DevHpetHlp;
3567
3568 LogFlow(("pdmR3DevHlp_HpetRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3569 return VINF_SUCCESS;
3570}
3571
3572
3573/** @interface_method_impl{PDMDEVHLPR3,pfnPciRawRegister} */
3574static DECLCALLBACK(int) pdmR3DevHlp_PciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
3575{
3576 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
3577 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3578 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3579
3580 /*
3581 * Validate input.
3582 */
3583 if (pPciRawReg->u32Version != PDM_PCIRAWREG_VERSION)
3584 {
3585 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciRawReg->u32Version, PDM_PCIRAWREG_VERSION));
3586 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3587 return VERR_INVALID_PARAMETER;
3588 }
3589
3590 if (!ppPciRawHlpR3)
3591 {
3592 Assert(ppPciRawHlpR3);
3593 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (ppPciRawHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3594 return VERR_INVALID_PARAMETER;
3595 }
3596
3597 /* set the helper pointer and return. */
3598 *ppPciRawHlpR3 = &g_pdmR3DevPciRawHlp;
3599 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3600 return VINF_SUCCESS;
3601}
3602
3603
3604/** @interface_method_impl{PDMDEVHLPR3,pfnDMACRegister} */
3605static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
3606{
3607 PDMDEV_ASSERT_DEVINS(pDevIns);
3608 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3609 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",
3610 pDevIns->pReg->szName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
3611 pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
3612
3613 /*
3614 * Validate input.
3615 */
3616 if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
3617 {
3618 AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
3619 PDM_DMACREG_VERSION));
3620 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (version)\n",
3621 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3622 return VERR_INVALID_PARAMETER;
3623 }
3624 if ( !pDmacReg->pfnRun
3625 || !pDmacReg->pfnRegister
3626 || !pDmacReg->pfnReadMemory
3627 || !pDmacReg->pfnWriteMemory
3628 || !pDmacReg->pfnSetDREQ
3629 || !pDmacReg->pfnGetChannelMode)
3630 {
3631 Assert(pDmacReg->pfnRun);
3632 Assert(pDmacReg->pfnRegister);
3633 Assert(pDmacReg->pfnReadMemory);
3634 Assert(pDmacReg->pfnWriteMemory);
3635 Assert(pDmacReg->pfnSetDREQ);
3636 Assert(pDmacReg->pfnGetChannelMode);
3637 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3638 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3639 return VERR_INVALID_PARAMETER;
3640 }
3641
3642 if (!ppDmacHlp)
3643 {
3644 Assert(ppDmacHlp);
3645 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (ppDmacHlp)\n",
3646 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3647 return VERR_INVALID_PARAMETER;
3648 }
3649
3650 /*
3651 * Only one DMA device.
3652 */
3653 PVM pVM = pDevIns->Internal.s.pVMR3;
3654 if (pVM->pdm.s.pDmac)
3655 {
3656 AssertMsgFailed(("Only one DMA device is supported!\n"));
3657 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3658 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3659 return VERR_INVALID_PARAMETER;
3660 }
3661
3662 /*
3663 * Allocate and initialize pci bus structure.
3664 */
3665 int rc = VINF_SUCCESS;
3666 PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
3667 if (pDmac)
3668 {
3669 pDmac->pDevIns = pDevIns;
3670 pDmac->Reg = *pDmacReg;
3671 pVM->pdm.s.pDmac = pDmac;
3672
3673 /* set the helper pointer. */
3674 *ppDmacHlp = &g_pdmR3DevDmacHlp;
3675 Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
3676 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3677 }
3678 else
3679 rc = VERR_NO_MEMORY;
3680
3681 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3682 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3683 return rc;
3684}
3685
3686
3687/**
3688 * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
3689 */
3690static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbHeap)
3691{
3692 PDMDEV_ASSERT_DEVINS(pDevIns);
3693 PVM pVM = pDevIns->Internal.s.pVMR3;
3694 VM_ASSERT_EMT(pVM);
3695 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: GCPhys=%RGp pvHeap=%p cbHeap=%#x\n",
3696 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvHeap, cbHeap));
3697
3698 if (pVM->pdm.s.pvVMMDevHeap == NULL)
3699 {
3700 pVM->pdm.s.pvVMMDevHeap = pvHeap;
3701 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
3702 pVM->pdm.s.cbVMMDevHeap = cbHeap;
3703 pVM->pdm.s.cbVMMDevHeapLeft = cbHeap;
3704 }
3705 else
3706 {
3707 Assert(pVM->pdm.s.pvVMMDevHeap == pvHeap);
3708 Assert(pVM->pdm.s.cbVMMDevHeap == cbHeap);
3709 Assert(pVM->pdm.s.GCPhysVMMDevHeap != GCPhys || GCPhys == NIL_RTGCPHYS);
3710 if (pVM->pdm.s.GCPhysVMMDevHeap != GCPhys)
3711 {
3712 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
3713 if (pVM->pdm.s.pfnVMMDevHeapNotify)
3714 pVM->pdm.s.pfnVMMDevHeapNotify(pVM, pvHeap, GCPhys);
3715 }
3716 }
3717
3718 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: returns %Rrc\n",
3719 pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3720 return VINF_SUCCESS;
3721}
3722
3723
3724/**
3725 * @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister}
3726 */
3727static DECLCALLBACK(int) pdmR3DevHlp_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
3728{
3729 PDMDEV_ASSERT_DEVINS(pDevIns);
3730 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3731 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: pFWReg=%p:{.u32Version=%#x, .pfnIsHardReset=%p, .u32TheEnd=%#x} ppFwHlp=%p\n",
3732 pDevIns->pReg->szName, pDevIns->iInstance, pFwReg, pFwReg->u32Version, pFwReg->pfnIsHardReset, pFwReg->u32TheEnd, ppFwHlp));
3733
3734 /*
3735 * Validate input.
3736 */
3737 if (pFwReg->u32Version != PDM_FWREG_VERSION)
3738 {
3739 AssertMsgFailed(("u32Version=%#x expected %#x\n", pFwReg->u32Version, PDM_FWREG_VERSION));
3740 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (version)\n",
3741 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3742 return VERR_INVALID_PARAMETER;
3743 }
3744 if (!pFwReg->pfnIsHardReset)
3745 {
3746 Assert(pFwReg->pfnIsHardReset);
3747 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3748 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3749 return VERR_INVALID_PARAMETER;
3750 }
3751
3752 if (!ppFwHlp)
3753 {
3754 Assert(ppFwHlp);
3755 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (ppFwHlp)\n",
3756 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3757 return VERR_INVALID_PARAMETER;
3758 }
3759
3760 /*
3761 * Only one DMA device.
3762 */
3763 PVM pVM = pDevIns->Internal.s.pVMR3;
3764 if (pVM->pdm.s.pFirmware)
3765 {
3766 AssertMsgFailed(("Only one firmware device is supported!\n"));
3767 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
3768 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3769 return VERR_INVALID_PARAMETER;
3770 }
3771
3772 /*
3773 * Allocate and initialize pci bus structure.
3774 */
3775 int rc = VINF_SUCCESS;
3776 PPDMFW pFirmware = (PPDMFW)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pFirmware));
3777 if (pFirmware)
3778 {
3779 pFirmware->pDevIns = pDevIns;
3780 pFirmware->Reg = *pFwReg;
3781 pVM->pdm.s.pFirmware = pFirmware;
3782
3783 /* set the helper pointer. */
3784 *ppFwHlp = &g_pdmR3DevFirmwareHlp;
3785 Log(("PDM: Registered firmware device '%s'/%d pDevIns=%p\n",
3786 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3787 }
3788 else
3789 rc = VERR_NO_MEMORY;
3790
3791 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
3792 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3793 return rc;
3794}
3795
3796
3797/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
3798static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
3799{
3800 PDMDEV_ASSERT_DEVINS(pDevIns);
3801 PVM pVM = pDevIns->Internal.s.pVMR3;
3802 VM_ASSERT_EMT(pVM);
3803 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: fFlags=%#x VM_FF_RESET %d -> 1\n",
3804 pDevIns->pReg->szName, pDevIns->iInstance, fFlags, VM_FF_IS_SET(pVM, VM_FF_RESET)));
3805
3806 /*
3807 * We postpone this operation because we're likely to be inside a I/O instruction
3808 * and the EIP will be updated when we return.
3809 * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
3810 */
3811 bool fHaltOnReset;
3812 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
3813 if (RT_SUCCESS(rc) && fHaltOnReset)
3814 {
3815 Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
3816 rc = VINF_EM_HALT;
3817 }
3818 else
3819 {
3820 pVM->pdm.s.fResetFlags = fFlags;
3821 VM_FF_SET(pVM, VM_FF_RESET);
3822 rc = VINF_EM_RESET;
3823 }
3824
3825 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3826 return rc;
3827}
3828
3829
3830/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
3831static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
3832{
3833 int rc;
3834 PDMDEV_ASSERT_DEVINS(pDevIns);
3835 PVM pVM = pDevIns->Internal.s.pVMR3;
3836 VM_ASSERT_EMT(pVM);
3837 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
3838 pDevIns->pReg->szName, pDevIns->iInstance));
3839
3840 /** @todo Always take the SMP path - fewer code paths. */
3841 if (pVM->cCpus > 1)
3842 {
3843 /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
3844 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3Suspend, 2, pVM->pUVM, VMSUSPENDREASON_VM);
3845 AssertRC(rc);
3846 rc = VINF_EM_SUSPEND;
3847 }
3848 else
3849 rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
3850
3851 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3852 return rc;
3853}
3854
3855
3856/**
3857 * Worker for pdmR3DevHlp_VMSuspendSaveAndPowerOff that is invoked via a queued
3858 * EMT request to avoid deadlocks.
3859 *
3860 * @returns VBox status code fit for scheduling.
3861 * @param pVM The cross context VM structure.
3862 * @param pDevIns The device that triggered this action.
3863 */
3864static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker(PVM pVM, PPDMDEVINS pDevIns)
3865{
3866 /*
3867 * Suspend the VM first then do the saving.
3868 */
3869 int rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
3870 if (RT_SUCCESS(rc))
3871 {
3872 PUVM pUVM = pVM->pUVM;
3873 rc = pUVM->pVmm2UserMethods->pfnSaveState(pVM->pUVM->pVmm2UserMethods, pUVM);
3874
3875 /*
3876 * On success, power off the VM, on failure we'll leave it suspended.
3877 */
3878 if (RT_SUCCESS(rc))
3879 {
3880 rc = VMR3PowerOff(pVM->pUVM);
3881 if (RT_FAILURE(rc))
3882 LogRel(("%s/SSP: VMR3PowerOff failed: %Rrc\n", pDevIns->pReg->szName, rc));
3883 }
3884 else
3885 LogRel(("%s/SSP: pfnSaveState failed: %Rrc\n", pDevIns->pReg->szName, rc));
3886 }
3887 else
3888 LogRel(("%s/SSP: Suspend failed: %Rrc\n", pDevIns->pReg->szName, rc));
3889 return rc;
3890}
3891
3892
3893/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
3894static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
3895{
3896 PDMDEV_ASSERT_DEVINS(pDevIns);
3897 PVM pVM = pDevIns->Internal.s.pVMR3;
3898 VM_ASSERT_EMT(pVM);
3899 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d:\n",
3900 pDevIns->pReg->szName, pDevIns->iInstance));
3901
3902 int rc;
3903 if ( pVM->pUVM->pVmm2UserMethods
3904 && pVM->pUVM->pVmm2UserMethods->pfnSaveState)
3905 {
3906 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker, 2, pVM, pDevIns);
3907 if (RT_SUCCESS(rc))
3908 {
3909 LogRel(("%s: Suspending, Saving and Powering Off the VM\n", pDevIns->pReg->szName));
3910 rc = VINF_EM_SUSPEND;
3911 }
3912 }
3913 else
3914 rc = VERR_NOT_SUPPORTED;
3915
3916 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3917 return rc;
3918}
3919
3920
3921/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
3922static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
3923{
3924 int rc;
3925 PDMDEV_ASSERT_DEVINS(pDevIns);
3926 PVM pVM = pDevIns->Internal.s.pVMR3;
3927 VM_ASSERT_EMT(pVM);
3928 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
3929 pDevIns->pReg->szName, pDevIns->iInstance));
3930
3931 /** @todo Always take the SMP path - fewer code paths. */
3932 if (pVM->cCpus > 1)
3933 {
3934 /* We might be holding locks here and could cause a deadlock since
3935 VMR3PowerOff rendezvous with the other CPUs. */
3936 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3PowerOff, 1, pVM->pUVM);
3937 AssertRC(rc);
3938 /* Set the VCPU state to stopped here as well to make sure no
3939 inconsistency with the EM state occurs. */
3940 VMCPU_SET_STATE(VMMGetCpu(pVM), VMCPUSTATE_STOPPED);
3941 rc = VINF_EM_OFF;
3942 }
3943 else
3944 rc = VMR3PowerOff(pVM->pUVM);
3945
3946 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3947 return rc;
3948}
3949
3950
3951/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
3952static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
3953{
3954 PDMDEV_ASSERT_DEVINS(pDevIns);
3955 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3956
3957 bool fRc = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pVMR3));
3958
3959 LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pReg->szName, pDevIns->iInstance, fRc));
3960 return fRc;
3961}
3962
3963
3964/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
3965static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
3966{
3967 PDMDEV_ASSERT_DEVINS(pDevIns);
3968 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3969 LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, fEnable));
3970 PGMR3PhysSetA20(VMMGetCpu(pDevIns->Internal.s.pVMR3), fEnable);
3971}
3972
3973
3974/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
3975static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
3976 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
3977{
3978 PDMDEV_ASSERT_DEVINS(pDevIns);
3979 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3980
3981 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
3982 pDevIns->pReg->szName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
3983 AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
3984
3985 CPUMGetGuestCpuId(VMMGetCpu(pDevIns->Internal.s.pVMR3), iLeaf, 0 /*iSubLeaf*/, pEax, pEbx, pEcx, pEdx);
3986
3987 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
3988 pDevIns->pReg->szName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
3989}
3990
3991
3992/**
3993 * The device helper structure for trusted devices.
3994 */
3995const PDMDEVHLPR3 g_pdmR3DevHlpTrusted =
3996{
3997 PDM_DEVHLPR3_VERSION,
3998 pdmR3DevHlp_IoPortCreateEx,
3999 pdmR3DevHlp_IoPortMap,
4000 pdmR3DevHlp_IoPortUnmap,
4001 pdmR3DevHlp_IoPortGetMappingAddress,
4002 pdmR3DevHlp_MmioCreateEx,
4003 pdmR3DevHlp_MmioMap,
4004 pdmR3DevHlp_MmioUnmap,
4005 pdmR3DevHlp_MmioReduce,
4006 pdmR3DevHlp_MmioGetMappingAddress,
4007 pdmR3DevHlp_Mmio2Create,
4008 pdmR3DevHlp_Mmio2Destroy,
4009 pdmR3DevHlp_Mmio2Map,
4010 pdmR3DevHlp_Mmio2Unmap,
4011 pdmR3DevHlp_Mmio2Reduce,
4012 pdmR3DevHlp_Mmio2GetMappingAddress,
4013 pdmR3DevHlp_Mmio2ChangeRegionNo,
4014 pdmR3DevHlp_ROMRegister,
4015 pdmR3DevHlp_ROMProtectShadow,
4016 pdmR3DevHlp_SSMRegister,
4017 SSMR3PutStruct,
4018 SSMR3PutStructEx,
4019 SSMR3PutBool,
4020 SSMR3PutU8,
4021 SSMR3PutS8,
4022 SSMR3PutU16,
4023 SSMR3PutS16,
4024 SSMR3PutU32,
4025 SSMR3PutS32,
4026 SSMR3PutU64,
4027 SSMR3PutS64,
4028 SSMR3PutU128,
4029 SSMR3PutS128,
4030 SSMR3PutUInt,
4031 SSMR3PutSInt,
4032 SSMR3PutGCUInt,
4033 SSMR3PutGCUIntReg,
4034 SSMR3PutGCPhys32,
4035 SSMR3PutGCPhys64,
4036 SSMR3PutGCPhys,
4037 SSMR3PutGCPtr,
4038 SSMR3PutGCUIntPtr,
4039 SSMR3PutRCPtr,
4040 SSMR3PutIOPort,
4041 SSMR3PutSel,
4042 SSMR3PutMem,
4043 SSMR3PutStrZ,
4044 SSMR3GetStruct,
4045 SSMR3GetStructEx,
4046 SSMR3GetBool,
4047 SSMR3GetBoolV,
4048 SSMR3GetU8,
4049 SSMR3GetU8V,
4050 SSMR3GetS8,
4051 SSMR3GetS8V,
4052 SSMR3GetU16,
4053 SSMR3GetU16V,
4054 SSMR3GetS16,
4055 SSMR3GetS16V,
4056 SSMR3GetU32,
4057 SSMR3GetU32V,
4058 SSMR3GetS32,
4059 SSMR3GetS32V,
4060 SSMR3GetU64,
4061 SSMR3GetU64V,
4062 SSMR3GetS64,
4063 SSMR3GetS64V,
4064 SSMR3GetU128,
4065 SSMR3GetU128V,
4066 SSMR3GetS128,
4067 SSMR3GetS128V,
4068 SSMR3GetGCPhys32,
4069 SSMR3GetGCPhys32V,
4070 SSMR3GetGCPhys64,
4071 SSMR3GetGCPhys64V,
4072 SSMR3GetGCPhys,
4073 SSMR3GetGCPhysV,
4074 SSMR3GetUInt,
4075 SSMR3GetSInt,
4076 SSMR3GetGCUInt,
4077 SSMR3GetGCUIntReg,
4078 SSMR3GetGCPtr,
4079 SSMR3GetGCUIntPtr,
4080 SSMR3GetRCPtr,
4081 SSMR3GetIOPort,
4082 SSMR3GetSel,
4083 SSMR3GetMem,
4084 SSMR3GetStrZ,
4085 SSMR3GetStrZEx,
4086 SSMR3Skip,
4087 SSMR3SkipToEndOfUnit,
4088 SSMR3SetLoadError,
4089 SSMR3SetLoadErrorV,
4090 SSMR3SetCfgError,
4091 SSMR3SetCfgErrorV,
4092 SSMR3HandleGetStatus,
4093 SSMR3HandleGetAfter,
4094 SSMR3HandleIsLiveSave,
4095 SSMR3HandleMaxDowntime,
4096 SSMR3HandleHostBits,
4097 SSMR3HandleRevision,
4098 SSMR3HandleVersion,
4099 SSMR3HandleHostOSAndArch,
4100 pdmR3DevHlp_TMTimerCreate,
4101 pdmR3DevHlp_TimerCreate,
4102 pdmR3DevHlp_TimerToPtr,
4103 pdmR3DevHlp_TimerFromMicro,
4104 pdmR3DevHlp_TimerFromMilli,
4105 pdmR3DevHlp_TimerFromNano,
4106 pdmR3DevHlp_TimerGet,
4107 pdmR3DevHlp_TimerGetFreq,
4108 pdmR3DevHlp_TimerGetNano,
4109 pdmR3DevHlp_TimerIsActive,
4110 pdmR3DevHlp_TimerIsLockOwner,
4111 pdmR3DevHlp_TimerLockClock,
4112 pdmR3DevHlp_TimerLockClock2,
4113 pdmR3DevHlp_TimerSet,
4114 pdmR3DevHlp_TimerSetFrequencyHint,
4115 pdmR3DevHlp_TimerSetMicro,
4116 pdmR3DevHlp_TimerSetMillies,
4117 pdmR3DevHlp_TimerSetNano,
4118 pdmR3DevHlp_TimerSetRelative,
4119 pdmR3DevHlp_TimerStop,
4120 pdmR3DevHlp_TimerUnlockClock,
4121 pdmR3DevHlp_TimerUnlockClock2,
4122 pdmR3DevHlp_TimerSetCritSect,
4123 pdmR3DevHlp_TimerSave,
4124 pdmR3DevHlp_TimerLoad,
4125 pdmR3DevHlp_TimerDestroy,
4126 TMR3TimerSkip,
4127 pdmR3DevHlp_TMUtcNow,
4128 CFGMR3Exists,
4129 CFGMR3QueryType,
4130 CFGMR3QuerySize,
4131 CFGMR3QueryInteger,
4132 CFGMR3QueryIntegerDef,
4133 CFGMR3QueryString,
4134 CFGMR3QueryStringDef,
4135 CFGMR3QueryBytes,
4136 CFGMR3QueryU64,
4137 CFGMR3QueryU64Def,
4138 CFGMR3QueryS64,
4139 CFGMR3QueryS64Def,
4140 CFGMR3QueryU32,
4141 CFGMR3QueryU32Def,
4142 CFGMR3QueryS32,
4143 CFGMR3QueryS32Def,
4144 CFGMR3QueryU16,
4145 CFGMR3QueryU16Def,
4146 CFGMR3QueryS16,
4147 CFGMR3QueryS16Def,
4148 CFGMR3QueryU8,
4149 CFGMR3QueryU8Def,
4150 CFGMR3QueryS8,
4151 CFGMR3QueryS8Def,
4152 CFGMR3QueryBool,
4153 CFGMR3QueryBoolDef,
4154 CFGMR3QueryPort,
4155 CFGMR3QueryPortDef,
4156 CFGMR3QueryUInt,
4157 CFGMR3QueryUIntDef,
4158 CFGMR3QuerySInt,
4159 CFGMR3QuerySIntDef,
4160 CFGMR3QueryPtr,
4161 CFGMR3QueryPtrDef,
4162 CFGMR3QueryGCPtr,
4163 CFGMR3QueryGCPtrDef,
4164 CFGMR3QueryGCPtrU,
4165 CFGMR3QueryGCPtrUDef,
4166 CFGMR3QueryGCPtrS,
4167 CFGMR3QueryGCPtrSDef,
4168 CFGMR3QueryStringAlloc,
4169 CFGMR3QueryStringAllocDef,
4170 CFGMR3GetParent,
4171 CFGMR3GetChild,
4172 CFGMR3GetChildF,
4173 CFGMR3GetChildFV,
4174 CFGMR3GetFirstChild,
4175 CFGMR3GetNextChild,
4176 CFGMR3GetName,
4177 CFGMR3GetNameLen,
4178 CFGMR3AreChildrenValid,
4179 CFGMR3GetFirstValue,
4180 CFGMR3GetNextValue,
4181 CFGMR3GetValueName,
4182 CFGMR3GetValueNameLen,
4183 CFGMR3GetValueType,
4184 CFGMR3AreValuesValid,
4185 CFGMR3ValidateConfig,
4186 pdmR3DevHlp_PhysRead,
4187 pdmR3DevHlp_PhysWrite,
4188 pdmR3DevHlp_PhysGCPhys2CCPtr,
4189 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4190 pdmR3DevHlp_PhysReleasePageMappingLock,
4191 pdmR3DevHlp_PhysReadGCVirt,
4192 pdmR3DevHlp_PhysWriteGCVirt,
4193 pdmR3DevHlp_PhysGCPtr2GCPhys,
4194 pdmR3DevHlp_MMHeapAlloc,
4195 pdmR3DevHlp_MMHeapAllocZ,
4196 pdmR3DevHlp_MMHeapFree,
4197 pdmR3DevHlp_VMState,
4198 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4199 pdmR3DevHlp_VMSetError,
4200 pdmR3DevHlp_VMSetErrorV,
4201 pdmR3DevHlp_VMSetRuntimeError,
4202 pdmR3DevHlp_VMSetRuntimeErrorV,
4203 pdmR3DevHlp_DBGFStopV,
4204 pdmR3DevHlp_DBGFInfoRegister,
4205 pdmR3DevHlp_DBGFInfoRegisterArgv,
4206 pdmR3DevHlp_DBGFRegRegister,
4207 pdmR3DevHlp_DBGFTraceBuf,
4208 pdmR3DevHlp_STAMRegister,
4209 pdmR3DevHlp_STAMRegisterV,
4210 pdmR3DevHlp_PCIRegister,
4211 pdmR3DevHlp_PCIRegisterMsi,
4212 pdmR3DevHlp_PCIIORegionRegister,
4213 pdmR3DevHlp_PCIInterceptConfigAccesses,
4214 pdmR3DevHlp_PCIConfigWrite,
4215 pdmR3DevHlp_PCIConfigRead,
4216 pdmR3DevHlp_PCIPhysRead,
4217 pdmR3DevHlp_PCIPhysWrite,
4218 pdmR3DevHlp_PCISetIrq,
4219 pdmR3DevHlp_PCISetIrqNoWait,
4220 pdmR3DevHlp_ISASetIrq,
4221 pdmR3DevHlp_ISASetIrqNoWait,
4222 pdmR3DevHlp_DriverAttach,
4223 pdmR3DevHlp_DriverDetach,
4224 pdmR3DevHlp_DriverReconfigure,
4225 pdmR3DevHlp_QueueCreatePtr,
4226 pdmR3DevHlp_QueueCreate,
4227 pdmR3DevHlp_QueueToPtr,
4228 pdmR3DevHlp_QueueAlloc,
4229 pdmR3DevHlp_QueueInsert,
4230 pdmR3DevHlp_QueueInsertEx,
4231 pdmR3DevHlp_QueueFlushIfNecessary,
4232 pdmR3DevHlp_TaskCreate,
4233 pdmR3DevHlp_TaskTrigger,
4234 pdmR3DevHlp_SUPSemEventCreate,
4235 pdmR3DevHlp_SUPSemEventClose,
4236 pdmR3DevHlp_SUPSemEventSignal,
4237 pdmR3DevHlp_SUPSemEventWaitNoResume,
4238 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
4239 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
4240 pdmR3DevHlp_SUPSemEventGetResolution,
4241 pdmR3DevHlp_SUPSemEventMultiCreate,
4242 pdmR3DevHlp_SUPSemEventMultiClose,
4243 pdmR3DevHlp_SUPSemEventMultiSignal,
4244 pdmR3DevHlp_SUPSemEventMultiReset,
4245 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
4246 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
4247 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
4248 pdmR3DevHlp_SUPSemEventMultiGetResolution,
4249 pdmR3DevHlp_CritSectInit,
4250 pdmR3DevHlp_CritSectGetNop,
4251 pdmR3DevHlp_CritSectGetNopR0,
4252 pdmR3DevHlp_CritSectGetNopRC,
4253 pdmR3DevHlp_SetDeviceCritSect,
4254 pdmR3DevHlp_CritSectYield,
4255 pdmR3DevHlp_CritSectEnter,
4256 pdmR3DevHlp_CritSectEnterDebug,
4257 pdmR3DevHlp_CritSectTryEnter,
4258 pdmR3DevHlp_CritSectTryEnterDebug,
4259 pdmR3DevHlp_CritSectLeave,
4260 pdmR3DevHlp_CritSectIsOwner,
4261 pdmR3DevHlp_CritSectIsInitialized,
4262 pdmR3DevHlp_CritSectHasWaiters,
4263 pdmR3DevHlp_CritSectGetRecursion,
4264 pdmR3DevHlp_CritSectScheduleExitEvent,
4265 pdmR3DevHlp_CritSectDelete,
4266 pdmR3DevHlp_ThreadCreate,
4267 PDMR3ThreadDestroy,
4268 PDMR3ThreadIAmSuspending,
4269 PDMR3ThreadIAmRunning,
4270 PDMR3ThreadSleep,
4271 PDMR3ThreadSuspend,
4272 PDMR3ThreadResume,
4273 pdmR3DevHlp_SetAsyncNotification,
4274 pdmR3DevHlp_AsyncNotificationCompleted,
4275 pdmR3DevHlp_RTCRegister,
4276 pdmR3DevHlp_PCIBusRegister,
4277 pdmR3DevHlp_IommuRegister,
4278 pdmR3DevHlp_PICRegister,
4279 pdmR3DevHlp_ApicRegister,
4280 pdmR3DevHlp_IoApicRegister,
4281 pdmR3DevHlp_HpetRegister,
4282 pdmR3DevHlp_PciRawRegister,
4283 pdmR3DevHlp_DMACRegister,
4284 pdmR3DevHlp_DMARegister,
4285 pdmR3DevHlp_DMAReadMemory,
4286 pdmR3DevHlp_DMAWriteMemory,
4287 pdmR3DevHlp_DMASetDREQ,
4288 pdmR3DevHlp_DMAGetChannelMode,
4289 pdmR3DevHlp_DMASchedule,
4290 pdmR3DevHlp_CMOSWrite,
4291 pdmR3DevHlp_CMOSRead,
4292 pdmR3DevHlp_AssertEMT,
4293 pdmR3DevHlp_AssertOther,
4294 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4295 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4296 pdmR3DevHlp_CallR0,
4297 pdmR3DevHlp_VMGetSuspendReason,
4298 pdmR3DevHlp_VMGetResumeReason,
4299 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4300 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4301 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4302 pdmR3DevHlp_CpuGetGuestMicroarch,
4303 0,
4304 0,
4305 0,
4306 0,
4307 0,
4308 0,
4309 0,
4310 0,
4311 0,
4312 0,
4313 pdmR3DevHlp_GetUVM,
4314 pdmR3DevHlp_GetVM,
4315 pdmR3DevHlp_GetVMCPU,
4316 pdmR3DevHlp_GetCurrentCpuId,
4317 pdmR3DevHlp_RegisterVMMDevHeap,
4318 pdmR3DevHlp_FirmwareRegister,
4319 pdmR3DevHlp_VMReset,
4320 pdmR3DevHlp_VMSuspend,
4321 pdmR3DevHlp_VMSuspendSaveAndPowerOff,
4322 pdmR3DevHlp_VMPowerOff,
4323 pdmR3DevHlp_A20IsEnabled,
4324 pdmR3DevHlp_A20Set,
4325 pdmR3DevHlp_GetCpuId,
4326 pdmR3DevHlp_TMTimeVirtGet,
4327 pdmR3DevHlp_TMTimeVirtGetFreq,
4328 pdmR3DevHlp_TMTimeVirtGetNano,
4329 pdmR3DevHlp_GetSupDrvSession,
4330 pdmR3DevHlp_QueryGenericUserObject,
4331 pdmR3DevHlp_PGMHandlerPhysicalTypeRegister,
4332 PDM_DEVHLPR3_VERSION /* the end */
4333};
4334
4335
4336#ifdef VBOX_WITH_DBGF_TRACING
4337/**
4338 * The device helper structure for trusted devices - tracing variant.
4339 */
4340const PDMDEVHLPR3 g_pdmR3DevHlpTracing =
4341{
4342 PDM_DEVHLPR3_VERSION,
4343 pdmR3DevHlpTracing_IoPortCreateEx,
4344 pdmR3DevHlpTracing_IoPortMap,
4345 pdmR3DevHlpTracing_IoPortUnmap,
4346 pdmR3DevHlp_IoPortGetMappingAddress,
4347 pdmR3DevHlpTracing_MmioCreateEx,
4348 pdmR3DevHlpTracing_MmioMap,
4349 pdmR3DevHlpTracing_MmioUnmap,
4350 pdmR3DevHlp_MmioReduce,
4351 pdmR3DevHlp_MmioGetMappingAddress,
4352 pdmR3DevHlp_Mmio2Create,
4353 pdmR3DevHlp_Mmio2Destroy,
4354 pdmR3DevHlp_Mmio2Map,
4355 pdmR3DevHlp_Mmio2Unmap,
4356 pdmR3DevHlp_Mmio2Reduce,
4357 pdmR3DevHlp_Mmio2GetMappingAddress,
4358 pdmR3DevHlp_Mmio2ChangeRegionNo,
4359 pdmR3DevHlp_ROMRegister,
4360 pdmR3DevHlp_ROMProtectShadow,
4361 pdmR3DevHlp_SSMRegister,
4362 SSMR3PutStruct,
4363 SSMR3PutStructEx,
4364 SSMR3PutBool,
4365 SSMR3PutU8,
4366 SSMR3PutS8,
4367 SSMR3PutU16,
4368 SSMR3PutS16,
4369 SSMR3PutU32,
4370 SSMR3PutS32,
4371 SSMR3PutU64,
4372 SSMR3PutS64,
4373 SSMR3PutU128,
4374 SSMR3PutS128,
4375 SSMR3PutUInt,
4376 SSMR3PutSInt,
4377 SSMR3PutGCUInt,
4378 SSMR3PutGCUIntReg,
4379 SSMR3PutGCPhys32,
4380 SSMR3PutGCPhys64,
4381 SSMR3PutGCPhys,
4382 SSMR3PutGCPtr,
4383 SSMR3PutGCUIntPtr,
4384 SSMR3PutRCPtr,
4385 SSMR3PutIOPort,
4386 SSMR3PutSel,
4387 SSMR3PutMem,
4388 SSMR3PutStrZ,
4389 SSMR3GetStruct,
4390 SSMR3GetStructEx,
4391 SSMR3GetBool,
4392 SSMR3GetBoolV,
4393 SSMR3GetU8,
4394 SSMR3GetU8V,
4395 SSMR3GetS8,
4396 SSMR3GetS8V,
4397 SSMR3GetU16,
4398 SSMR3GetU16V,
4399 SSMR3GetS16,
4400 SSMR3GetS16V,
4401 SSMR3GetU32,
4402 SSMR3GetU32V,
4403 SSMR3GetS32,
4404 SSMR3GetS32V,
4405 SSMR3GetU64,
4406 SSMR3GetU64V,
4407 SSMR3GetS64,
4408 SSMR3GetS64V,
4409 SSMR3GetU128,
4410 SSMR3GetU128V,
4411 SSMR3GetS128,
4412 SSMR3GetS128V,
4413 SSMR3GetGCPhys32,
4414 SSMR3GetGCPhys32V,
4415 SSMR3GetGCPhys64,
4416 SSMR3GetGCPhys64V,
4417 SSMR3GetGCPhys,
4418 SSMR3GetGCPhysV,
4419 SSMR3GetUInt,
4420 SSMR3GetSInt,
4421 SSMR3GetGCUInt,
4422 SSMR3GetGCUIntReg,
4423 SSMR3GetGCPtr,
4424 SSMR3GetGCUIntPtr,
4425 SSMR3GetRCPtr,
4426 SSMR3GetIOPort,
4427 SSMR3GetSel,
4428 SSMR3GetMem,
4429 SSMR3GetStrZ,
4430 SSMR3GetStrZEx,
4431 SSMR3Skip,
4432 SSMR3SkipToEndOfUnit,
4433 SSMR3SetLoadError,
4434 SSMR3SetLoadErrorV,
4435 SSMR3SetCfgError,
4436 SSMR3SetCfgErrorV,
4437 SSMR3HandleGetStatus,
4438 SSMR3HandleGetAfter,
4439 SSMR3HandleIsLiveSave,
4440 SSMR3HandleMaxDowntime,
4441 SSMR3HandleHostBits,
4442 SSMR3HandleRevision,
4443 SSMR3HandleVersion,
4444 SSMR3HandleHostOSAndArch,
4445 pdmR3DevHlp_TMTimerCreate,
4446 pdmR3DevHlp_TimerCreate,
4447 pdmR3DevHlp_TimerToPtr,
4448 pdmR3DevHlp_TimerFromMicro,
4449 pdmR3DevHlp_TimerFromMilli,
4450 pdmR3DevHlp_TimerFromNano,
4451 pdmR3DevHlp_TimerGet,
4452 pdmR3DevHlp_TimerGetFreq,
4453 pdmR3DevHlp_TimerGetNano,
4454 pdmR3DevHlp_TimerIsActive,
4455 pdmR3DevHlp_TimerIsLockOwner,
4456 pdmR3DevHlp_TimerLockClock,
4457 pdmR3DevHlp_TimerLockClock2,
4458 pdmR3DevHlp_TimerSet,
4459 pdmR3DevHlp_TimerSetFrequencyHint,
4460 pdmR3DevHlp_TimerSetMicro,
4461 pdmR3DevHlp_TimerSetMillies,
4462 pdmR3DevHlp_TimerSetNano,
4463 pdmR3DevHlp_TimerSetRelative,
4464 pdmR3DevHlp_TimerStop,
4465 pdmR3DevHlp_TimerUnlockClock,
4466 pdmR3DevHlp_TimerUnlockClock2,
4467 pdmR3DevHlp_TimerSetCritSect,
4468 pdmR3DevHlp_TimerSave,
4469 pdmR3DevHlp_TimerLoad,
4470 pdmR3DevHlp_TimerDestroy,
4471 TMR3TimerSkip,
4472 pdmR3DevHlp_TMUtcNow,
4473 CFGMR3Exists,
4474 CFGMR3QueryType,
4475 CFGMR3QuerySize,
4476 CFGMR3QueryInteger,
4477 CFGMR3QueryIntegerDef,
4478 CFGMR3QueryString,
4479 CFGMR3QueryStringDef,
4480 CFGMR3QueryBytes,
4481 CFGMR3QueryU64,
4482 CFGMR3QueryU64Def,
4483 CFGMR3QueryS64,
4484 CFGMR3QueryS64Def,
4485 CFGMR3QueryU32,
4486 CFGMR3QueryU32Def,
4487 CFGMR3QueryS32,
4488 CFGMR3QueryS32Def,
4489 CFGMR3QueryU16,
4490 CFGMR3QueryU16Def,
4491 CFGMR3QueryS16,
4492 CFGMR3QueryS16Def,
4493 CFGMR3QueryU8,
4494 CFGMR3QueryU8Def,
4495 CFGMR3QueryS8,
4496 CFGMR3QueryS8Def,
4497 CFGMR3QueryBool,
4498 CFGMR3QueryBoolDef,
4499 CFGMR3QueryPort,
4500 CFGMR3QueryPortDef,
4501 CFGMR3QueryUInt,
4502 CFGMR3QueryUIntDef,
4503 CFGMR3QuerySInt,
4504 CFGMR3QuerySIntDef,
4505 CFGMR3QueryPtr,
4506 CFGMR3QueryPtrDef,
4507 CFGMR3QueryGCPtr,
4508 CFGMR3QueryGCPtrDef,
4509 CFGMR3QueryGCPtrU,
4510 CFGMR3QueryGCPtrUDef,
4511 CFGMR3QueryGCPtrS,
4512 CFGMR3QueryGCPtrSDef,
4513 CFGMR3QueryStringAlloc,
4514 CFGMR3QueryStringAllocDef,
4515 CFGMR3GetParent,
4516 CFGMR3GetChild,
4517 CFGMR3GetChildF,
4518 CFGMR3GetChildFV,
4519 CFGMR3GetFirstChild,
4520 CFGMR3GetNextChild,
4521 CFGMR3GetName,
4522 CFGMR3GetNameLen,
4523 CFGMR3AreChildrenValid,
4524 CFGMR3GetFirstValue,
4525 CFGMR3GetNextValue,
4526 CFGMR3GetValueName,
4527 CFGMR3GetValueNameLen,
4528 CFGMR3GetValueType,
4529 CFGMR3AreValuesValid,
4530 CFGMR3ValidateConfig,
4531 pdmR3DevHlpTracing_PhysRead,
4532 pdmR3DevHlpTracing_PhysWrite,
4533 pdmR3DevHlp_PhysGCPhys2CCPtr,
4534 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4535 pdmR3DevHlp_PhysReleasePageMappingLock,
4536 pdmR3DevHlp_PhysReadGCVirt,
4537 pdmR3DevHlp_PhysWriteGCVirt,
4538 pdmR3DevHlp_PhysGCPtr2GCPhys,
4539 pdmR3DevHlp_MMHeapAlloc,
4540 pdmR3DevHlp_MMHeapAllocZ,
4541 pdmR3DevHlp_MMHeapFree,
4542 pdmR3DevHlp_VMState,
4543 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4544 pdmR3DevHlp_VMSetError,
4545 pdmR3DevHlp_VMSetErrorV,
4546 pdmR3DevHlp_VMSetRuntimeError,
4547 pdmR3DevHlp_VMSetRuntimeErrorV,
4548 pdmR3DevHlp_DBGFStopV,
4549 pdmR3DevHlp_DBGFInfoRegister,
4550 pdmR3DevHlp_DBGFInfoRegisterArgv,
4551 pdmR3DevHlp_DBGFRegRegister,
4552 pdmR3DevHlp_DBGFTraceBuf,
4553 pdmR3DevHlp_STAMRegister,
4554 pdmR3DevHlp_STAMRegisterV,
4555 pdmR3DevHlp_PCIRegister,
4556 pdmR3DevHlp_PCIRegisterMsi,
4557 pdmR3DevHlp_PCIIORegionRegister,
4558 pdmR3DevHlp_PCIInterceptConfigAccesses,
4559 pdmR3DevHlp_PCIConfigWrite,
4560 pdmR3DevHlp_PCIConfigRead,
4561 pdmR3DevHlpTracing_PCIPhysRead,
4562 pdmR3DevHlpTracing_PCIPhysWrite,
4563 pdmR3DevHlpTracing_PCISetIrq,
4564 pdmR3DevHlpTracing_PCISetIrqNoWait,
4565 pdmR3DevHlpTracing_ISASetIrq,
4566 pdmR3DevHlpTracing_ISASetIrqNoWait,
4567 pdmR3DevHlp_DriverAttach,
4568 pdmR3DevHlp_DriverDetach,
4569 pdmR3DevHlp_DriverReconfigure,
4570 pdmR3DevHlp_QueueCreatePtr,
4571 pdmR3DevHlp_QueueCreate,
4572 pdmR3DevHlp_QueueToPtr,
4573 pdmR3DevHlp_QueueAlloc,
4574 pdmR3DevHlp_QueueInsert,
4575 pdmR3DevHlp_QueueInsertEx,
4576 pdmR3DevHlp_QueueFlushIfNecessary,
4577 pdmR3DevHlp_TaskCreate,
4578 pdmR3DevHlp_TaskTrigger,
4579 pdmR3DevHlp_SUPSemEventCreate,
4580 pdmR3DevHlp_SUPSemEventClose,
4581 pdmR3DevHlp_SUPSemEventSignal,
4582 pdmR3DevHlp_SUPSemEventWaitNoResume,
4583 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
4584 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
4585 pdmR3DevHlp_SUPSemEventGetResolution,
4586 pdmR3DevHlp_SUPSemEventMultiCreate,
4587 pdmR3DevHlp_SUPSemEventMultiClose,
4588 pdmR3DevHlp_SUPSemEventMultiSignal,
4589 pdmR3DevHlp_SUPSemEventMultiReset,
4590 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
4591 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
4592 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
4593 pdmR3DevHlp_SUPSemEventMultiGetResolution,
4594 pdmR3DevHlp_CritSectInit,
4595 pdmR3DevHlp_CritSectGetNop,
4596 pdmR3DevHlp_CritSectGetNopR0,
4597 pdmR3DevHlp_CritSectGetNopRC,
4598 pdmR3DevHlp_SetDeviceCritSect,
4599 pdmR3DevHlp_CritSectYield,
4600 pdmR3DevHlp_CritSectEnter,
4601 pdmR3DevHlp_CritSectEnterDebug,
4602 pdmR3DevHlp_CritSectTryEnter,
4603 pdmR3DevHlp_CritSectTryEnterDebug,
4604 pdmR3DevHlp_CritSectLeave,
4605 pdmR3DevHlp_CritSectIsOwner,
4606 pdmR3DevHlp_CritSectIsInitialized,
4607 pdmR3DevHlp_CritSectHasWaiters,
4608 pdmR3DevHlp_CritSectGetRecursion,
4609 pdmR3DevHlp_CritSectScheduleExitEvent,
4610 pdmR3DevHlp_CritSectDelete,
4611 pdmR3DevHlp_ThreadCreate,
4612 PDMR3ThreadDestroy,
4613 PDMR3ThreadIAmSuspending,
4614 PDMR3ThreadIAmRunning,
4615 PDMR3ThreadSleep,
4616 PDMR3ThreadSuspend,
4617 PDMR3ThreadResume,
4618 pdmR3DevHlp_SetAsyncNotification,
4619 pdmR3DevHlp_AsyncNotificationCompleted,
4620 pdmR3DevHlp_RTCRegister,
4621 pdmR3DevHlp_PCIBusRegister,
4622 pdmR3DevHlp_IommuRegister,
4623 pdmR3DevHlp_PICRegister,
4624 pdmR3DevHlp_ApicRegister,
4625 pdmR3DevHlp_IoApicRegister,
4626 pdmR3DevHlp_HpetRegister,
4627 pdmR3DevHlp_PciRawRegister,
4628 pdmR3DevHlp_DMACRegister,
4629 pdmR3DevHlp_DMARegister,
4630 pdmR3DevHlp_DMAReadMemory,
4631 pdmR3DevHlp_DMAWriteMemory,
4632 pdmR3DevHlp_DMASetDREQ,
4633 pdmR3DevHlp_DMAGetChannelMode,
4634 pdmR3DevHlp_DMASchedule,
4635 pdmR3DevHlp_CMOSWrite,
4636 pdmR3DevHlp_CMOSRead,
4637 pdmR3DevHlp_AssertEMT,
4638 pdmR3DevHlp_AssertOther,
4639 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4640 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4641 pdmR3DevHlp_CallR0,
4642 pdmR3DevHlp_VMGetSuspendReason,
4643 pdmR3DevHlp_VMGetResumeReason,
4644 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4645 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4646 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4647 pdmR3DevHlp_CpuGetGuestMicroarch,
4648 0,
4649 0,
4650 0,
4651 0,
4652 0,
4653 0,
4654 0,
4655 0,
4656 0,
4657 0,
4658 pdmR3DevHlp_GetUVM,
4659 pdmR3DevHlp_GetVM,
4660 pdmR3DevHlp_GetVMCPU,
4661 pdmR3DevHlp_GetCurrentCpuId,
4662 pdmR3DevHlp_RegisterVMMDevHeap,
4663 pdmR3DevHlp_FirmwareRegister,
4664 pdmR3DevHlp_VMReset,
4665 pdmR3DevHlp_VMSuspend,
4666 pdmR3DevHlp_VMSuspendSaveAndPowerOff,
4667 pdmR3DevHlp_VMPowerOff,
4668 pdmR3DevHlp_A20IsEnabled,
4669 pdmR3DevHlp_A20Set,
4670 pdmR3DevHlp_GetCpuId,
4671 pdmR3DevHlp_TMTimeVirtGet,
4672 pdmR3DevHlp_TMTimeVirtGetFreq,
4673 pdmR3DevHlp_TMTimeVirtGetNano,
4674 pdmR3DevHlp_GetSupDrvSession,
4675 pdmR3DevHlp_QueryGenericUserObject,
4676 pdmR3DevHlp_PGMHandlerPhysicalTypeRegister,
4677 PDM_DEVHLPR3_VERSION /* the end */
4678};
4679#endif
4680
4681
4682
4683
4684/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
4685static DECLCALLBACK(PUVM) pdmR3DevHlp_Untrusted_GetUVM(PPDMDEVINS pDevIns)
4686{
4687 PDMDEV_ASSERT_DEVINS(pDevIns);
4688 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4689 return NULL;
4690}
4691
4692
4693/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
4694static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
4695{
4696 PDMDEV_ASSERT_DEVINS(pDevIns);
4697 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4698 return NULL;
4699}
4700
4701
4702/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
4703static DECLCALLBACK(PVMCPU) pdmR3DevHlp_Untrusted_GetVMCPU(PPDMDEVINS pDevIns)
4704{
4705 PDMDEV_ASSERT_DEVINS(pDevIns);
4706 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4707 return NULL;
4708}
4709
4710
4711/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
4712static DECLCALLBACK(VMCPUID) pdmR3DevHlp_Untrusted_GetCurrentCpuId(PPDMDEVINS pDevIns)
4713{
4714 PDMDEV_ASSERT_DEVINS(pDevIns);
4715 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4716 return NIL_VMCPUID;
4717}
4718
4719
4720/** @interface_method_impl{PDMDEVHLPR3,pfnRegisterVMMDevHeap} */
4721static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys,
4722 RTR3PTR pvHeap, unsigned cbHeap)
4723{
4724 PDMDEV_ASSERT_DEVINS(pDevIns);
4725 NOREF(GCPhys); NOREF(pvHeap); NOREF(cbHeap);
4726 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4727 return VERR_ACCESS_DENIED;
4728}
4729
4730
4731/** @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister} */
4732static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
4733{
4734 PDMDEV_ASSERT_DEVINS(pDevIns);
4735 NOREF(pFwReg); NOREF(ppFwHlp);
4736 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4737 return VERR_ACCESS_DENIED;
4738}
4739
4740
4741/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
4742static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
4743{
4744 PDMDEV_ASSERT_DEVINS(pDevIns); NOREF(fFlags);
4745 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4746 return VERR_ACCESS_DENIED;
4747}
4748
4749
4750/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
4751static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
4752{
4753 PDMDEV_ASSERT_DEVINS(pDevIns);
4754 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4755 return VERR_ACCESS_DENIED;
4756}
4757
4758
4759/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
4760static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
4761{
4762 PDMDEV_ASSERT_DEVINS(pDevIns);
4763 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4764 return VERR_ACCESS_DENIED;
4765}
4766
4767
4768/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
4769static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
4770{
4771 PDMDEV_ASSERT_DEVINS(pDevIns);
4772 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4773 return VERR_ACCESS_DENIED;
4774}
4775
4776
4777/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
4778static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
4779{
4780 PDMDEV_ASSERT_DEVINS(pDevIns);
4781 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4782 return false;
4783}
4784
4785
4786/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
4787static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
4788{
4789 PDMDEV_ASSERT_DEVINS(pDevIns);
4790 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4791 NOREF(fEnable);
4792}
4793
4794
4795/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
4796static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
4797 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
4798{
4799 PDMDEV_ASSERT_DEVINS(pDevIns);
4800 NOREF(iLeaf); NOREF(pEax); NOREF(pEbx); NOREF(pEcx); NOREF(pEdx);
4801 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4802}
4803
4804
4805/** @interface_method_impl{PDMDEVHLPR3,pfnGetSupDrvSession} */
4806static DECLCALLBACK(PSUPDRVSESSION) pdmR3DevHlp_Untrusted_GetSupDrvSession(PPDMDEVINS pDevIns)
4807{
4808 PDMDEV_ASSERT_DEVINS(pDevIns);
4809 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4810 return (PSUPDRVSESSION)0;
4811}
4812
4813
4814/** @interface_method_impl{PDMDEVHLPR3,pfnQueryGenericUserObject} */
4815static DECLCALLBACK(void *) pdmR3DevHlp_Untrusted_QueryGenericUserObject(PPDMDEVINS pDevIns, PCRTUUID pUuid)
4816{
4817 PDMDEV_ASSERT_DEVINS(pDevIns);
4818 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d %RTuuid\n",
4819 pDevIns->pReg->szName, pDevIns->iInstance, pUuid));
4820 return NULL;
4821}
4822
4823
4824/** @interface_method_impl{PDMDEVHLPR3,pfnPGMHandlerPhysicalTypeRegister} */
4825static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PGMHandlerPhysicalTypeRegister(PPDMDEVINS pDevIns, PGMPHYSHANDLERKIND enmKind,
4826 R3PTRTYPE(PFNPGMPHYSHANDLER) pfnHandlerR3,
4827 const char *pszHandlerR0, const char *pszPfHandlerR0,
4828 const char *pszHandlerRC, const char *pszPfHandlerRC,
4829 const char *pszDesc, PPGMPHYSHANDLERTYPE phType)
4830{
4831 PDMDEV_ASSERT_DEVINS(pDevIns);
4832 RT_NOREF(enmKind, pfnHandlerR3, pszHandlerR0, pszPfHandlerR0, pszHandlerRC, pszPfHandlerRC, pszDesc, phType);
4833 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
4834 pDevIns->pReg->szName, pDevIns->iInstance));
4835 return VERR_ACCESS_DENIED;
4836}
4837
4838
4839/**
4840 * The device helper structure for non-trusted devices.
4841 */
4842const PDMDEVHLPR3 g_pdmR3DevHlpUnTrusted =
4843{
4844 PDM_DEVHLPR3_VERSION,
4845 pdmR3DevHlp_IoPortCreateEx,
4846 pdmR3DevHlp_IoPortMap,
4847 pdmR3DevHlp_IoPortUnmap,
4848 pdmR3DevHlp_IoPortGetMappingAddress,
4849 pdmR3DevHlp_MmioCreateEx,
4850 pdmR3DevHlp_MmioMap,
4851 pdmR3DevHlp_MmioUnmap,
4852 pdmR3DevHlp_MmioReduce,
4853 pdmR3DevHlp_MmioGetMappingAddress,
4854 pdmR3DevHlp_Mmio2Create,
4855 pdmR3DevHlp_Mmio2Destroy,
4856 pdmR3DevHlp_Mmio2Map,
4857 pdmR3DevHlp_Mmio2Unmap,
4858 pdmR3DevHlp_Mmio2Reduce,
4859 pdmR3DevHlp_Mmio2GetMappingAddress,
4860 pdmR3DevHlp_Mmio2ChangeRegionNo,
4861 pdmR3DevHlp_ROMRegister,
4862 pdmR3DevHlp_ROMProtectShadow,
4863 pdmR3DevHlp_SSMRegister,
4864 SSMR3PutStruct,
4865 SSMR3PutStructEx,
4866 SSMR3PutBool,
4867 SSMR3PutU8,
4868 SSMR3PutS8,
4869 SSMR3PutU16,
4870 SSMR3PutS16,
4871 SSMR3PutU32,
4872 SSMR3PutS32,
4873 SSMR3PutU64,
4874 SSMR3PutS64,
4875 SSMR3PutU128,
4876 SSMR3PutS128,
4877 SSMR3PutUInt,
4878 SSMR3PutSInt,
4879 SSMR3PutGCUInt,
4880 SSMR3PutGCUIntReg,
4881 SSMR3PutGCPhys32,
4882 SSMR3PutGCPhys64,
4883 SSMR3PutGCPhys,
4884 SSMR3PutGCPtr,
4885 SSMR3PutGCUIntPtr,
4886 SSMR3PutRCPtr,
4887 SSMR3PutIOPort,
4888 SSMR3PutSel,
4889 SSMR3PutMem,
4890 SSMR3PutStrZ,
4891 SSMR3GetStruct,
4892 SSMR3GetStructEx,
4893 SSMR3GetBool,
4894 SSMR3GetBoolV,
4895 SSMR3GetU8,
4896 SSMR3GetU8V,
4897 SSMR3GetS8,
4898 SSMR3GetS8V,
4899 SSMR3GetU16,
4900 SSMR3GetU16V,
4901 SSMR3GetS16,
4902 SSMR3GetS16V,
4903 SSMR3GetU32,
4904 SSMR3GetU32V,
4905 SSMR3GetS32,
4906 SSMR3GetS32V,
4907 SSMR3GetU64,
4908 SSMR3GetU64V,
4909 SSMR3GetS64,
4910 SSMR3GetS64V,
4911 SSMR3GetU128,
4912 SSMR3GetU128V,
4913 SSMR3GetS128,
4914 SSMR3GetS128V,
4915 SSMR3GetGCPhys32,
4916 SSMR3GetGCPhys32V,
4917 SSMR3GetGCPhys64,
4918 SSMR3GetGCPhys64V,
4919 SSMR3GetGCPhys,
4920 SSMR3GetGCPhysV,
4921 SSMR3GetUInt,
4922 SSMR3GetSInt,
4923 SSMR3GetGCUInt,
4924 SSMR3GetGCUIntReg,
4925 SSMR3GetGCPtr,
4926 SSMR3GetGCUIntPtr,
4927 SSMR3GetRCPtr,
4928 SSMR3GetIOPort,
4929 SSMR3GetSel,
4930 SSMR3GetMem,
4931 SSMR3GetStrZ,
4932 SSMR3GetStrZEx,
4933 SSMR3Skip,
4934 SSMR3SkipToEndOfUnit,
4935 SSMR3SetLoadError,
4936 SSMR3SetLoadErrorV,
4937 SSMR3SetCfgError,
4938 SSMR3SetCfgErrorV,
4939 SSMR3HandleGetStatus,
4940 SSMR3HandleGetAfter,
4941 SSMR3HandleIsLiveSave,
4942 SSMR3HandleMaxDowntime,
4943 SSMR3HandleHostBits,
4944 SSMR3HandleRevision,
4945 SSMR3HandleVersion,
4946 SSMR3HandleHostOSAndArch,
4947 pdmR3DevHlp_TMTimerCreate,
4948 pdmR3DevHlp_TimerCreate,
4949 pdmR3DevHlp_TimerToPtr,
4950 pdmR3DevHlp_TimerFromMicro,
4951 pdmR3DevHlp_TimerFromMilli,
4952 pdmR3DevHlp_TimerFromNano,
4953 pdmR3DevHlp_TimerGet,
4954 pdmR3DevHlp_TimerGetFreq,
4955 pdmR3DevHlp_TimerGetNano,
4956 pdmR3DevHlp_TimerIsActive,
4957 pdmR3DevHlp_TimerIsLockOwner,
4958 pdmR3DevHlp_TimerLockClock,
4959 pdmR3DevHlp_TimerLockClock2,
4960 pdmR3DevHlp_TimerSet,
4961 pdmR3DevHlp_TimerSetFrequencyHint,
4962 pdmR3DevHlp_TimerSetMicro,
4963 pdmR3DevHlp_TimerSetMillies,
4964 pdmR3DevHlp_TimerSetNano,
4965 pdmR3DevHlp_TimerSetRelative,
4966 pdmR3DevHlp_TimerStop,
4967 pdmR3DevHlp_TimerUnlockClock,
4968 pdmR3DevHlp_TimerUnlockClock2,
4969 pdmR3DevHlp_TimerSetCritSect,
4970 pdmR3DevHlp_TimerSave,
4971 pdmR3DevHlp_TimerLoad,
4972 pdmR3DevHlp_TimerDestroy,
4973 TMR3TimerSkip,
4974 pdmR3DevHlp_TMUtcNow,
4975 CFGMR3Exists,
4976 CFGMR3QueryType,
4977 CFGMR3QuerySize,
4978 CFGMR3QueryInteger,
4979 CFGMR3QueryIntegerDef,
4980 CFGMR3QueryString,
4981 CFGMR3QueryStringDef,
4982 CFGMR3QueryBytes,
4983 CFGMR3QueryU64,
4984 CFGMR3QueryU64Def,
4985 CFGMR3QueryS64,
4986 CFGMR3QueryS64Def,
4987 CFGMR3QueryU32,
4988 CFGMR3QueryU32Def,
4989 CFGMR3QueryS32,
4990 CFGMR3QueryS32Def,
4991 CFGMR3QueryU16,
4992 CFGMR3QueryU16Def,
4993 CFGMR3QueryS16,
4994 CFGMR3QueryS16Def,
4995 CFGMR3QueryU8,
4996 CFGMR3QueryU8Def,
4997 CFGMR3QueryS8,
4998 CFGMR3QueryS8Def,
4999 CFGMR3QueryBool,
5000 CFGMR3QueryBoolDef,
5001 CFGMR3QueryPort,
5002 CFGMR3QueryPortDef,
5003 CFGMR3QueryUInt,
5004 CFGMR3QueryUIntDef,
5005 CFGMR3QuerySInt,
5006 CFGMR3QuerySIntDef,
5007 CFGMR3QueryPtr,
5008 CFGMR3QueryPtrDef,
5009 CFGMR3QueryGCPtr,
5010 CFGMR3QueryGCPtrDef,
5011 CFGMR3QueryGCPtrU,
5012 CFGMR3QueryGCPtrUDef,
5013 CFGMR3QueryGCPtrS,
5014 CFGMR3QueryGCPtrSDef,
5015 CFGMR3QueryStringAlloc,
5016 CFGMR3QueryStringAllocDef,
5017 CFGMR3GetParent,
5018 CFGMR3GetChild,
5019 CFGMR3GetChildF,
5020 CFGMR3GetChildFV,
5021 CFGMR3GetFirstChild,
5022 CFGMR3GetNextChild,
5023 CFGMR3GetName,
5024 CFGMR3GetNameLen,
5025 CFGMR3AreChildrenValid,
5026 CFGMR3GetFirstValue,
5027 CFGMR3GetNextValue,
5028 CFGMR3GetValueName,
5029 CFGMR3GetValueNameLen,
5030 CFGMR3GetValueType,
5031 CFGMR3AreValuesValid,
5032 CFGMR3ValidateConfig,
5033 pdmR3DevHlp_PhysRead,
5034 pdmR3DevHlp_PhysWrite,
5035 pdmR3DevHlp_PhysGCPhys2CCPtr,
5036 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
5037 pdmR3DevHlp_PhysReleasePageMappingLock,
5038 pdmR3DevHlp_PhysReadGCVirt,
5039 pdmR3DevHlp_PhysWriteGCVirt,
5040 pdmR3DevHlp_PhysGCPtr2GCPhys,
5041 pdmR3DevHlp_MMHeapAlloc,
5042 pdmR3DevHlp_MMHeapAllocZ,
5043 pdmR3DevHlp_MMHeapFree,
5044 pdmR3DevHlp_VMState,
5045 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
5046 pdmR3DevHlp_VMSetError,
5047 pdmR3DevHlp_VMSetErrorV,
5048 pdmR3DevHlp_VMSetRuntimeError,
5049 pdmR3DevHlp_VMSetRuntimeErrorV,
5050 pdmR3DevHlp_DBGFStopV,
5051 pdmR3DevHlp_DBGFInfoRegister,
5052 pdmR3DevHlp_DBGFInfoRegisterArgv,
5053 pdmR3DevHlp_DBGFRegRegister,
5054 pdmR3DevHlp_DBGFTraceBuf,
5055 pdmR3DevHlp_STAMRegister,
5056 pdmR3DevHlp_STAMRegisterV,
5057 pdmR3DevHlp_PCIRegister,
5058 pdmR3DevHlp_PCIRegisterMsi,
5059 pdmR3DevHlp_PCIIORegionRegister,
5060 pdmR3DevHlp_PCIInterceptConfigAccesses,
5061 pdmR3DevHlp_PCIConfigWrite,
5062 pdmR3DevHlp_PCIConfigRead,
5063 pdmR3DevHlp_PCIPhysRead,
5064 pdmR3DevHlp_PCIPhysWrite,
5065 pdmR3DevHlp_PCISetIrq,
5066 pdmR3DevHlp_PCISetIrqNoWait,
5067 pdmR3DevHlp_ISASetIrq,
5068 pdmR3DevHlp_ISASetIrqNoWait,
5069 pdmR3DevHlp_DriverAttach,
5070 pdmR3DevHlp_DriverDetach,
5071 pdmR3DevHlp_DriverReconfigure,
5072 pdmR3DevHlp_QueueCreatePtr,
5073 pdmR3DevHlp_QueueCreate,
5074 pdmR3DevHlp_QueueToPtr,
5075 pdmR3DevHlp_QueueAlloc,
5076 pdmR3DevHlp_QueueInsert,
5077 pdmR3DevHlp_QueueInsertEx,
5078 pdmR3DevHlp_QueueFlushIfNecessary,
5079 pdmR3DevHlp_TaskCreate,
5080 pdmR3DevHlp_TaskTrigger,
5081 pdmR3DevHlp_SUPSemEventCreate,
5082 pdmR3DevHlp_SUPSemEventClose,
5083 pdmR3DevHlp_SUPSemEventSignal,
5084 pdmR3DevHlp_SUPSemEventWaitNoResume,
5085 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
5086 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
5087 pdmR3DevHlp_SUPSemEventGetResolution,
5088 pdmR3DevHlp_SUPSemEventMultiCreate,
5089 pdmR3DevHlp_SUPSemEventMultiClose,
5090 pdmR3DevHlp_SUPSemEventMultiSignal,
5091 pdmR3DevHlp_SUPSemEventMultiReset,
5092 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
5093 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
5094 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
5095 pdmR3DevHlp_SUPSemEventMultiGetResolution,
5096 pdmR3DevHlp_CritSectInit,
5097 pdmR3DevHlp_CritSectGetNop,
5098 pdmR3DevHlp_CritSectGetNopR0,
5099 pdmR3DevHlp_CritSectGetNopRC,
5100 pdmR3DevHlp_SetDeviceCritSect,
5101 pdmR3DevHlp_CritSectYield,
5102 pdmR3DevHlp_CritSectEnter,
5103 pdmR3DevHlp_CritSectEnterDebug,
5104 pdmR3DevHlp_CritSectTryEnter,
5105 pdmR3DevHlp_CritSectTryEnterDebug,
5106 pdmR3DevHlp_CritSectLeave,
5107 pdmR3DevHlp_CritSectIsOwner,
5108 pdmR3DevHlp_CritSectIsInitialized,
5109 pdmR3DevHlp_CritSectHasWaiters,
5110 pdmR3DevHlp_CritSectGetRecursion,
5111 pdmR3DevHlp_CritSectScheduleExitEvent,
5112 pdmR3DevHlp_CritSectDelete,
5113 pdmR3DevHlp_ThreadCreate,
5114 PDMR3ThreadDestroy,
5115 PDMR3ThreadIAmSuspending,
5116 PDMR3ThreadIAmRunning,
5117 PDMR3ThreadSleep,
5118 PDMR3ThreadSuspend,
5119 PDMR3ThreadResume,
5120 pdmR3DevHlp_SetAsyncNotification,
5121 pdmR3DevHlp_AsyncNotificationCompleted,
5122 pdmR3DevHlp_RTCRegister,
5123 pdmR3DevHlp_PCIBusRegister,
5124 pdmR3DevHlp_IommuRegister,
5125 pdmR3DevHlp_PICRegister,
5126 pdmR3DevHlp_ApicRegister,
5127 pdmR3DevHlp_IoApicRegister,
5128 pdmR3DevHlp_HpetRegister,
5129 pdmR3DevHlp_PciRawRegister,
5130 pdmR3DevHlp_DMACRegister,
5131 pdmR3DevHlp_DMARegister,
5132 pdmR3DevHlp_DMAReadMemory,
5133 pdmR3DevHlp_DMAWriteMemory,
5134 pdmR3DevHlp_DMASetDREQ,
5135 pdmR3DevHlp_DMAGetChannelMode,
5136 pdmR3DevHlp_DMASchedule,
5137 pdmR3DevHlp_CMOSWrite,
5138 pdmR3DevHlp_CMOSRead,
5139 pdmR3DevHlp_AssertEMT,
5140 pdmR3DevHlp_AssertOther,
5141 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
5142 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
5143 pdmR3DevHlp_CallR0,
5144 pdmR3DevHlp_VMGetSuspendReason,
5145 pdmR3DevHlp_VMGetResumeReason,
5146 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
5147 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
5148 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
5149 pdmR3DevHlp_CpuGetGuestMicroarch,
5150 0,
5151 0,
5152 0,
5153 0,
5154 0,
5155 0,
5156 0,
5157 0,
5158 0,
5159 0,
5160 pdmR3DevHlp_Untrusted_GetUVM,
5161 pdmR3DevHlp_Untrusted_GetVM,
5162 pdmR3DevHlp_Untrusted_GetVMCPU,
5163 pdmR3DevHlp_Untrusted_GetCurrentCpuId,
5164 pdmR3DevHlp_Untrusted_RegisterVMMDevHeap,
5165 pdmR3DevHlp_Untrusted_FirmwareRegister,
5166 pdmR3DevHlp_Untrusted_VMReset,
5167 pdmR3DevHlp_Untrusted_VMSuspend,
5168 pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff,
5169 pdmR3DevHlp_Untrusted_VMPowerOff,
5170 pdmR3DevHlp_Untrusted_A20IsEnabled,
5171 pdmR3DevHlp_Untrusted_A20Set,
5172 pdmR3DevHlp_Untrusted_GetCpuId,
5173 pdmR3DevHlp_TMTimeVirtGet,
5174 pdmR3DevHlp_TMTimeVirtGetFreq,
5175 pdmR3DevHlp_TMTimeVirtGetNano,
5176 pdmR3DevHlp_Untrusted_GetSupDrvSession,
5177 pdmR3DevHlp_Untrusted_QueryGenericUserObject,
5178 pdmR3DevHlp_Untrusted_PGMHandlerPhysicalTypeRegister,
5179 PDM_DEVHLPR3_VERSION /* the end */
5180};
5181
5182
5183
5184/**
5185 * Queue consumer callback for internal component.
5186 *
5187 * @returns Success indicator.
5188 * If false the item will not be removed and the flushing will stop.
5189 * @param pVM The cross context VM structure.
5190 * @param pItem The item to consume. Upon return this item will be freed.
5191 */
5192DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
5193{
5194 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
5195 LogFlow(("pdmR3DevHlpQueueConsumer: enmOp=%d pDevIns=%p\n", pTask->enmOp, pTask->pDevInsR3));
5196 switch (pTask->enmOp)
5197 {
5198 case PDMDEVHLPTASKOP_ISA_SET_IRQ:
5199 PDMIsaSetIrq(pVM, pTask->u.IsaSetIRQ.iIrq, pTask->u.IsaSetIRQ.iLevel, pTask->u.IsaSetIRQ.uTagSrc);
5200 break;
5201
5202 case PDMDEVHLPTASKOP_PCI_SET_IRQ:
5203 {
5204 /* Same as pdmR3DevHlp_PCISetIrq, except we've got a tag already. */
5205 PPDMPCIDEV pPciDev = pTask->u.PciSetIRQ.pPciDevR3;
5206 if (pPciDev)
5207 {
5208 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
5209 AssertBreak(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
5210 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
5211
5212 pdmLock(pVM);
5213 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, pTask->u.PciSetIRQ.iIrq,
5214 pTask->u.PciSetIRQ.iLevel, pTask->u.PciSetIRQ.uTagSrc);
5215 pdmUnlock(pVM);
5216 }
5217 else
5218 AssertReleaseMsgFailed(("No PCI device registered!\n"));
5219 break;
5220 }
5221
5222 case PDMDEVHLPTASKOP_IOAPIC_SET_IRQ:
5223 {
5224 PDMIoApicSetIrq(pVM, pTask->u.IoApicSetIRQ.uBusDevFn, pTask->u.IoApicSetIRQ.iIrq, pTask->u.IoApicSetIRQ.iLevel,
5225 pTask->u.IoApicSetIRQ.uTagSrc);
5226 break;
5227 }
5228
5229 default:
5230 AssertReleaseMsgFailed(("Invalid operation %d\n", pTask->enmOp));
5231 break;
5232 }
5233 return true;
5234}
5235
5236/** @} */
5237
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