VirtualBox

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

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

AMD IOMMU: bugref:9654: Add PDM interfaces for pfnPCIPhysGCPhys2CCPtr[ReadOnly] and merge IOMMU memory read/write interface into memory access interface with a flag.

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