VirtualBox

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

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

AMD IOMMU: bugref:9654 Handle the case where an access might result in non-contiguous physical addresses after address translation via the IOMMU.

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