VirtualBox

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

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

PDMDevHlp/IOM: MMIO hack. bugref:9218

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

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