VirtualBox

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

最後變更 在這個檔案從84854是 84854,由 vboxsync 提交於 5 年 前

VMM/pdmR3DevHlp_MmioCreateEx: Must mangle description for saved state. bugref:9218

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

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