VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/PDMR0DevHlp.cpp@ 84809

Last change on this file since 84809 was 84809, checked in by vboxsync, 5 years ago

AMD IOMMU: bugref:9654 Use the proper PCI bus number. Not the Bus array index.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 68.6 KB
Line 
1/* $Id: PDMR0DevHlp.cpp 84809 2020-06-12 06:49:41Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, R0 Device Helper parts.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_PDM_DEVICE
23#define PDMPCIDEV_INCLUDE_PRIVATE /* Hack to get pdmpcidevint.h included at the right point. */
24#include "PDMInternal.h"
25#include <VBox/vmm/pdm.h>
26#include <VBox/vmm/apic.h>
27#include <VBox/vmm/mm.h>
28#include <VBox/vmm/pgm.h>
29#include <VBox/vmm/gvm.h>
30#include <VBox/vmm/vmm.h>
31#include <VBox/vmm/vmcc.h>
32#include <VBox/vmm/gvmm.h>
33
34#include <VBox/log.h>
35#include <VBox/err.h>
36#include <VBox/sup.h>
37#include <iprt/asm.h>
38#include <iprt/assert.h>
39#include <iprt/ctype.h>
40#include <iprt/string.h>
41
42#include "dtrace/VBoxVMM.h"
43#include "PDMInline.h"
44
45
46/*********************************************************************************************************************************
47* Global Variables *
48*********************************************************************************************************************************/
49RT_C_DECLS_BEGIN
50extern DECLEXPORT(const PDMDEVHLPR0) g_pdmR0DevHlp;
51extern DECLEXPORT(const PDMPICHLP) g_pdmR0PicHlp;
52extern DECLEXPORT(const PDMIOAPICHLP) g_pdmR0IoApicHlp;
53extern DECLEXPORT(const PDMPCIHLPR0) g_pdmR0PciHlp;
54extern DECLEXPORT(const PDMIOMMUHLPR0) g_pdmR0IommuHlp;
55extern DECLEXPORT(const PDMHPETHLPR0) g_pdmR0HpetHlp;
56extern DECLEXPORT(const PDMPCIRAWHLPR0) g_pdmR0PciRawHlp;
57RT_C_DECLS_END
58
59
60/*********************************************************************************************************************************
61* Internal Functions *
62*********************************************************************************************************************************/
63
64
65/** @name Ring-0 Device Helpers
66 * @{
67 */
68
69/** @interface_method_impl{PDMDEVHLPR0,pfnIoPortSetUpContextEx} */
70static DECLCALLBACK(int) pdmR0DevHlp_IoPortSetUpContextEx(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts,
71 PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
72 PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr,
73 void *pvUser)
74{
75 PDMDEV_ASSERT_DEVINS(pDevIns);
76 LogFlow(("pdmR0DevHlp_IoPortSetUpContextEx: caller='%s'/%d: hIoPorts=%#x pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pvUser=%p\n",
77 pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser));
78 PGVM pGVM = pDevIns->Internal.s.pGVM;
79 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
80 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
81
82 int rc = IOMR0IoPortSetUpContext(pGVM, pDevIns, hIoPorts, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser);
83
84 LogFlow(("pdmR0DevHlp_IoPortSetUpContextEx: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
85 return rc;
86}
87
88
89/** @interface_method_impl{PDMDEVHLPR0,pfnMmioSetUpContextEx} */
90static DECLCALLBACK(int) pdmR0DevHlp_MmioSetUpContextEx(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, PFNIOMMMIONEWWRITE pfnWrite,
91 PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill, void *pvUser)
92{
93 PDMDEV_ASSERT_DEVINS(pDevIns);
94 LogFlow(("pdmR0DevHlp_MmioSetUpContextEx: caller='%s'/%d: hRegion=%#x pfnWrite=%p pfnRead=%p pfnFill=%p pvUser=%p\n",
95 pDevIns->pReg->szName, pDevIns->iInstance, hRegion, pfnWrite, pfnRead, pfnFill, pvUser));
96 PGVM pGVM = pDevIns->Internal.s.pGVM;
97 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
98 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
99
100 int rc = IOMR0MmioSetUpContext(pGVM, pDevIns, hRegion, pfnWrite, pfnRead, pfnFill, pvUser);
101
102 LogFlow(("pdmR0DevHlp_MmioSetUpContextEx: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
103 return rc;
104}
105
106
107/** @interface_method_impl{PDMDEVHLPR0,pfnMmio2SetUpContext} */
108static DECLCALLBACK(int) pdmR0DevHlp_Mmio2SetUpContext(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion,
109 size_t offSub, size_t cbSub, void **ppvMapping)
110{
111 PDMDEV_ASSERT_DEVINS(pDevIns);
112 LogFlow(("pdmR0DevHlp_Mmio2SetUpContext: caller='%s'/%d: hRegion=%#x offSub=%#zx cbSub=%#zx ppvMapping=%p\n",
113 pDevIns->pReg->szName, pDevIns->iInstance, hRegion, offSub, cbSub, ppvMapping));
114 *ppvMapping = NULL;
115
116 PGVM pGVM = pDevIns->Internal.s.pGVM;
117 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
118 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
119
120 int rc = PGMR0PhysMMIO2MapKernel(pGVM, pDevIns, hRegion, offSub, cbSub, ppvMapping);
121
122 LogFlow(("pdmR0DevHlp_Mmio2SetUpContext: caller='%s'/%d: returns %Rrc (%p)\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *ppvMapping));
123 return rc;
124}
125
126
127/** @interface_method_impl{PDMDEVHLPR0,pfnPCIPhysRead} */
128static DECLCALLBACK(int) pdmR0DevHlp_PCIPhysRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
129 void *pvBuf, size_t cbRead, uint32_t fFlags)
130{
131 PDMDEV_ASSERT_DEVINS(pDevIns);
132 if (!pPciDev) /* NULL is an alias for the default PCI device. */
133 pPciDev = pDevIns->apPciDevs[0];
134 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
135 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
136
137#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
138 /*
139 * Just check the busmaster setting here and forward the request to the generic read helper.
140 */
141 if (PCIDevIsBusmaster(pPciDev))
142 { /* likely */ }
143 else
144 {
145 Log(("pdmRCDevHlp_PCIPhysRead: caller=%p/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbRead=%#zx\n",
146 pDevIns, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbRead));
147 memset(pvBuf, 0xff, cbRead);
148 return VERR_PDM_NOT_PCI_BUS_MASTER;
149 }
150#endif
151
152#ifdef VBOX_WITH_IOMMU_AMD
153 /** @todo IOMMU: Optimize/re-organize things here later. */
154 PGVM pGVM = pDevIns->Internal.s.pGVM;
155 PPDMIOMMUR0 pIommu = &pGVM->pdmr0.s.aIommus[0];
156 PPDMDEVINS pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
157 if ( pDevInsIommu
158 && pDevInsIommu != pDevIns)
159 {
160 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
161 Assert(idxBus < RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses));
162 PPDMPCIBUSR0 pBus = &pGVM->pdmr0.s.aPciBuses[idxBus];
163
164 RTGCPHYS GCPhysOut;
165 uint16_t const uDeviceId = VBOX_PCI_BUSDEVFN_MAKE(pBus->iBus, pPciDev->uDevFn);
166 int rc = pIommu->pfnMemRead(pDevInsIommu, uDeviceId, GCPhys, cbRead, &GCPhysOut);
167 if (RT_FAILURE(rc))
168 {
169 Log(("pdmR0DevHlp_PCIPhysRead: IOMMU translation failed. uDeviceId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDeviceId,
170 GCPhys, cbRead, rc));
171 return rc;
172 }
173 }
174#endif
175
176 return pDevIns->pHlpR0->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead, fFlags);
177}
178
179
180/** @interface_method_impl{PDMDEVHLPR0,pfnPCIPhysWrite} */
181static DECLCALLBACK(int) pdmR0DevHlp_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
182 const void *pvBuf, size_t cbWrite, uint32_t fFlags)
183{
184 PDMDEV_ASSERT_DEVINS(pDevIns);
185 if (!pPciDev) /* NULL is an alias for the default PCI device. */
186 pPciDev = pDevIns->apPciDevs[0];
187 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
188 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
189
190#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
191 /*
192 * Just check the busmaster setting here and forward the request to the generic read helper.
193 */
194 if (PCIDevIsBusmaster(pPciDev))
195 { /* likely */ }
196 else
197 {
198 Log(("pdmRCDevHlp_PCIPhysWrite: caller=%p/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n",
199 pDevIns, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
200 return VERR_PDM_NOT_PCI_BUS_MASTER;
201 }
202#endif
203
204#ifdef VBOX_WITH_IOMMU_AMD
205 /** @todo IOMMU: Optimize/re-organize things here later. */
206 PGVM pGVM = pDevIns->Internal.s.pGVM;
207 PPDMIOMMUR0 pIommu = &pGVM->pdmr0.s.aIommus[0];
208 PPDMDEVINS pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
209 if ( pDevInsIommu
210 && pDevInsIommu != pDevIns)
211 {
212 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
213 Assert(idxBus < RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses));
214 PPDMPCIBUSR0 pBus = &pGVM->pdmr0.s.aPciBuses[idxBus];
215
216 RTGCPHYS GCPhysOut;
217 uint16_t const uDeviceId = VBOX_PCI_BUSDEVFN_MAKE(pBus->iBus, pPciDev->uDevFn);
218 int rc = pIommu->pfnMemWrite(pDevInsIommu, uDeviceId, GCPhys, cbWrite, &GCPhysOut);
219 if (RT_FAILURE(rc))
220 {
221 Log(("pdmR0DevHlp_PCIPhysWrite: IOMMU translation failed. uDeviceId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDeviceId,
222 GCPhys, cbWrite, rc));
223 return rc;
224 }
225 }
226#endif
227
228 return pDevIns->pHlpR0->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite, fFlags);
229}
230
231
232/** @interface_method_impl{PDMDEVHLPR0,pfnPCISetIrq} */
233static DECLCALLBACK(void) pdmR0DevHlp_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
234{
235 PDMDEV_ASSERT_DEVINS(pDevIns);
236 if (!pPciDev) /* NULL is an alias for the default PCI device. */
237 pPciDev = pDevIns->apPciDevs[0];
238 AssertReturnVoid(pPciDev);
239 LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
240 pDevIns, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
241 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
242
243 PGVM pGVM = pDevIns->Internal.s.pGVM;
244 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
245 AssertReturnVoid(idxBus < RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses));
246 PPDMPCIBUSR0 pPciBusR0 = &pGVM->pdmr0.s.aPciBuses[idxBus];
247
248 pdmLock(pGVM);
249
250 uint32_t uTagSrc;
251 if (iLevel & PDM_IRQ_LEVEL_HIGH)
252 {
253 pDevIns->Internal.s.pIntR3R0->uLastIrqTag = uTagSrc = pdmCalcIrqTag(pGVM, pDevIns->Internal.s.pInsR3R0->idTracing);
254 if (iLevel == PDM_IRQ_LEVEL_HIGH)
255 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
256 else
257 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
258 }
259 else
260 uTagSrc = pDevIns->Internal.s.pIntR3R0->uLastIrqTag;
261
262 if (pPciBusR0->pDevInsR0)
263 {
264 pPciBusR0->pfnSetIrqR0(pPciBusR0->pDevInsR0, pPciDev, iIrq, iLevel, uTagSrc);
265
266 pdmUnlock(pGVM);
267
268 if (iLevel == PDM_IRQ_LEVEL_LOW)
269 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
270 }
271 else
272 {
273 pdmUnlock(pGVM);
274
275 /* queue for ring-3 execution. */
276 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM->pdm.s.pDevHlpQueueR0);
277 AssertReturnVoid(pTask);
278
279 pTask->enmOp = PDMDEVHLPTASKOP_PCI_SET_IRQ;
280 pTask->pDevInsR3 = PDMDEVINS_2_R3PTR(pDevIns);
281 pTask->u.PciSetIRQ.iIrq = iIrq;
282 pTask->u.PciSetIRQ.iLevel = iLevel;
283 pTask->u.PciSetIRQ.uTagSrc = uTagSrc;
284 pTask->u.PciSetIRQ.pPciDevR3 = MMHyperR0ToR3(pGVM, pPciDev);
285
286 PDMQueueInsertEx(pGVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
287 }
288
289 LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, uTagSrc));
290}
291
292
293/** @interface_method_impl{PDMDEVHLPR0,pfnISASetIrq} */
294static DECLCALLBACK(void) pdmR0DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
295{
296 PDMDEV_ASSERT_DEVINS(pDevIns);
297 LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
298 PGVM pGVM = pDevIns->Internal.s.pGVM;
299
300 pdmLock(pGVM);
301 uint32_t uTagSrc;
302 if (iLevel & PDM_IRQ_LEVEL_HIGH)
303 {
304 pDevIns->Internal.s.pIntR3R0->uLastIrqTag = uTagSrc = pdmCalcIrqTag(pGVM, pDevIns->Internal.s.pInsR3R0->idTracing);
305 if (iLevel == PDM_IRQ_LEVEL_HIGH)
306 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
307 else
308 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
309 }
310 else
311 uTagSrc = pDevIns->Internal.s.pIntR3R0->uLastIrqTag;
312
313 bool fRc = pdmR0IsaSetIrq(pGVM, iIrq, iLevel, uTagSrc);
314
315 if (iLevel == PDM_IRQ_LEVEL_LOW && fRc)
316 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
317 pdmUnlock(pGVM);
318 LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, uTagSrc));
319}
320
321
322/** @interface_method_impl{PDMDEVHLPR0,pfnPhysRead} */
323static DECLCALLBACK(int) pdmR0DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags)
324{
325 RT_NOREF(fFlags);
326
327 PDMDEV_ASSERT_DEVINS(pDevIns);
328 LogFlow(("pdmR0DevHlp_PhysRead: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
329 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
330
331 VBOXSTRICTRC rcStrict = PGMPhysRead(pDevIns->Internal.s.pGVM, GCPhys, pvBuf, cbRead, PGMACCESSORIGIN_DEVICE);
332 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
333
334 Log(("pdmR0DevHlp_PhysRead: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
335 return VBOXSTRICTRC_VAL(rcStrict);
336}
337
338
339/** @interface_method_impl{PDMDEVHLPR0,pfnPhysWrite} */
340static DECLCALLBACK(int) pdmR0DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags)
341{
342 RT_NOREF(fFlags);
343
344 PDMDEV_ASSERT_DEVINS(pDevIns);
345 LogFlow(("pdmR0DevHlp_PhysWrite: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
346 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
347
348 VBOXSTRICTRC rcStrict = PGMPhysWrite(pDevIns->Internal.s.pGVM, GCPhys, pvBuf, cbWrite, PGMACCESSORIGIN_DEVICE);
349 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
350
351 Log(("pdmR0DevHlp_PhysWrite: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
352 return VBOXSTRICTRC_VAL(rcStrict);
353}
354
355
356/** @interface_method_impl{PDMDEVHLPR0,pfnA20IsEnabled} */
357static DECLCALLBACK(bool) pdmR0DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
358{
359 PDMDEV_ASSERT_DEVINS(pDevIns);
360 LogFlow(("pdmR0DevHlp_A20IsEnabled: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
361
362 bool fEnabled = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pGVM));
363
364 Log(("pdmR0DevHlp_A20IsEnabled: caller=%p/%d: returns %RTbool\n", pDevIns, pDevIns->iInstance, fEnabled));
365 return fEnabled;
366}
367
368
369/** @interface_method_impl{PDMDEVHLPR0,pfnVMState} */
370static DECLCALLBACK(VMSTATE) pdmR0DevHlp_VMState(PPDMDEVINS pDevIns)
371{
372 PDMDEV_ASSERT_DEVINS(pDevIns);
373
374 VMSTATE enmVMState = pDevIns->Internal.s.pGVM->enmVMState;
375
376 LogFlow(("pdmR0DevHlp_VMState: caller=%p/%d: returns %d\n", pDevIns, pDevIns->iInstance, enmVMState));
377 return enmVMState;
378}
379
380
381/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetError} */
382static DECLCALLBACK(int) pdmR0DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
383{
384 PDMDEV_ASSERT_DEVINS(pDevIns);
385 va_list args;
386 va_start(args, pszFormat);
387 int rc2 = VMSetErrorV(pDevIns->Internal.s.pGVM, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
388 va_end(args);
389 return rc;
390}
391
392
393/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetErrorV} */
394static DECLCALLBACK(int) pdmR0DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
395{
396 PDMDEV_ASSERT_DEVINS(pDevIns);
397 int rc2 = VMSetErrorV(pDevIns->Internal.s.pGVM, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
398 return rc;
399}
400
401
402/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetRuntimeError} */
403static DECLCALLBACK(int) pdmR0DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
404{
405 PDMDEV_ASSERT_DEVINS(pDevIns);
406 va_list va;
407 va_start(va, pszFormat);
408 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pGVM, fFlags, pszErrorId, pszFormat, va);
409 va_end(va);
410 return rc;
411}
412
413
414/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetRuntimeErrorV} */
415static DECLCALLBACK(int) pdmR0DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
416{
417 PDMDEV_ASSERT_DEVINS(pDevIns);
418 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pGVM, fFlags, pszErrorId, pszFormat, va);
419 return rc;
420}
421
422
423
424/** @interface_method_impl{PDMDEVHLPR0,pfnGetVM} */
425static DECLCALLBACK(PVMCC) pdmR0DevHlp_GetVM(PPDMDEVINS pDevIns)
426{
427 PDMDEV_ASSERT_DEVINS(pDevIns);
428 LogFlow(("pdmR0DevHlp_GetVM: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
429 return pDevIns->Internal.s.pGVM;
430}
431
432
433/** @interface_method_impl{PDMDEVHLPR0,pfnGetVMCPU} */
434static DECLCALLBACK(PVMCPUCC) pdmR0DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
435{
436 PDMDEV_ASSERT_DEVINS(pDevIns);
437 LogFlow(("pdmR0DevHlp_GetVMCPU: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
438 return VMMGetCpu(pDevIns->Internal.s.pGVM);
439}
440
441
442/** @interface_method_impl{PDMDEVHLPRC,pfnGetCurrentCpuId} */
443static DECLCALLBACK(VMCPUID) pdmR0DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
444{
445 PDMDEV_ASSERT_DEVINS(pDevIns);
446 VMCPUID idCpu = VMMGetCpuId(pDevIns->Internal.s.pGVM);
447 LogFlow(("pdmR0DevHlp_GetCurrentCpuId: caller='%p'/%d for CPU %u\n", pDevIns, pDevIns->iInstance, idCpu));
448 return idCpu;
449}
450
451
452/** @interface_method_impl{PDMDEVHLPR0,pfnTimerToPtr} */
453static DECLCALLBACK(PTMTIMERR0) pdmR0DevHlp_TimerToPtr(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
454{
455 PDMDEV_ASSERT_DEVINS(pDevIns);
456 RT_NOREF(pDevIns);
457 return (PTMTIMERR0)MMHyperR3ToCC(pDevIns->Internal.s.pGVM, hTimer);
458}
459
460
461/** @interface_method_impl{PDMDEVHLPR0,pfnTimerFromMicro} */
462static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerFromMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicroSecs)
463{
464 return TMTimerFromMicro(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cMicroSecs);
465}
466
467
468/** @interface_method_impl{PDMDEVHLPR0,pfnTimerFromMilli} */
469static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerFromMilli(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliSecs)
470{
471 return TMTimerFromMilli(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cMilliSecs);
472}
473
474
475/** @interface_method_impl{PDMDEVHLPR0,pfnTimerFromNano} */
476static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerFromNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanoSecs)
477{
478 return TMTimerFromNano(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cNanoSecs);
479}
480
481/** @interface_method_impl{PDMDEVHLPR0,pfnTimerGet} */
482static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerGet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
483{
484 return TMTimerGet(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
485}
486
487
488/** @interface_method_impl{PDMDEVHLPR0,pfnTimerGetFreq} */
489static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerGetFreq(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
490{
491 return TMTimerGetFreq(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
492}
493
494
495/** @interface_method_impl{PDMDEVHLPR0,pfnTimerGetNano} */
496static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerGetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
497{
498 return TMTimerGetNano(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
499}
500
501
502/** @interface_method_impl{PDMDEVHLPR0,pfnTimerIsActive} */
503static DECLCALLBACK(bool) pdmR0DevHlp_TimerIsActive(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
504{
505 return TMTimerIsActive(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
506}
507
508
509/** @interface_method_impl{PDMDEVHLPR0,pfnTimerIsLockOwner} */
510static DECLCALLBACK(bool) pdmR0DevHlp_TimerIsLockOwner(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
511{
512 return TMTimerIsLockOwner(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
513}
514
515
516/** @interface_method_impl{PDMDEVHLPR0,pfnTimerLockClock} */
517static DECLCALLBACK(VBOXSTRICTRC) pdmR0DevHlp_TimerLockClock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, int rcBusy)
518{
519 return TMTimerLock(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), rcBusy);
520}
521
522
523/** @interface_method_impl{PDMDEVHLPR0,pfnTimerLockClock2} */
524static DECLCALLBACK(VBOXSTRICTRC) pdmR0DevHlp_TimerLockClock2(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer,
525 PPDMCRITSECT pCritSect, int rcBusy)
526{
527 VBOXSTRICTRC rc = TMTimerLock(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), rcBusy);
528 if (rc == VINF_SUCCESS)
529 {
530 rc = PDMCritSectEnter(pCritSect, rcBusy);
531 if (rc == VINF_SUCCESS)
532 return rc;
533 AssertRC(VBOXSTRICTRC_VAL(rc));
534 TMTimerUnlock(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
535 }
536 else
537 AssertRC(VBOXSTRICTRC_VAL(rc));
538 return rc;
539}
540
541
542/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSet} */
543static DECLCALLBACK(int) pdmR0DevHlp_TimerSet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t uExpire)
544{
545 return TMTimerSet(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), uExpire);
546}
547
548
549/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetFrequencyHint} */
550static DECLCALLBACK(int) pdmR0DevHlp_TimerSetFrequencyHint(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint32_t uHz)
551{
552 return TMTimerSetFrequencyHint(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), uHz);
553}
554
555
556/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetMicro} */
557static DECLCALLBACK(int) pdmR0DevHlp_TimerSetMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext)
558{
559 return TMTimerSetMicro(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cMicrosToNext);
560}
561
562
563/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetMillies} */
564static DECLCALLBACK(int) pdmR0DevHlp_TimerSetMillies(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext)
565{
566 return TMTimerSetMillies(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cMilliesToNext);
567}
568
569
570/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetNano} */
571static DECLCALLBACK(int) pdmR0DevHlp_TimerSetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanosToNext)
572{
573 return TMTimerSetNano(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cNanosToNext);
574}
575
576
577/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetRelative} */
578static DECLCALLBACK(int) pdmR0DevHlp_TimerSetRelative(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now)
579{
580 return TMTimerSetRelative(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cTicksToNext, pu64Now);
581}
582
583
584/** @interface_method_impl{PDMDEVHLPR0,pfnTimerStop} */
585static DECLCALLBACK(int) pdmR0DevHlp_TimerStop(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
586{
587 return TMTimerStop(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
588}
589
590
591/** @interface_method_impl{PDMDEVHLPR0,pfnTimerUnlockClock} */
592static DECLCALLBACK(void) pdmR0DevHlp_TimerUnlockClock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
593{
594 TMTimerUnlock(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
595}
596
597
598/** @interface_method_impl{PDMDEVHLPR0,pfnTimerUnlockClock2} */
599static DECLCALLBACK(void) pdmR0DevHlp_TimerUnlockClock2(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect)
600{
601 TMTimerUnlock(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
602 int rc = PDMCritSectLeave(pCritSect);
603 AssertRC(rc);
604}
605
606
607/** @interface_method_impl{PDMDEVHLPR0,pfnTMTimeVirtGet} */
608static DECLCALLBACK(uint64_t) pdmR0DevHlp_TMTimeVirtGet(PPDMDEVINS pDevIns)
609{
610 PDMDEV_ASSERT_DEVINS(pDevIns);
611 LogFlow(("pdmR0DevHlp_TMTimeVirtGet: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
612 return TMVirtualGet(pDevIns->Internal.s.pGVM);
613}
614
615
616/** @interface_method_impl{PDMDEVHLPR0,pfnTMTimeVirtGetFreq} */
617static DECLCALLBACK(uint64_t) pdmR0DevHlp_TMTimeVirtGetFreq(PPDMDEVINS pDevIns)
618{
619 PDMDEV_ASSERT_DEVINS(pDevIns);
620 LogFlow(("pdmR0DevHlp_TMTimeVirtGetFreq: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
621 return TMVirtualGetFreq(pDevIns->Internal.s.pGVM);
622}
623
624
625/** @interface_method_impl{PDMDEVHLPR0,pfnTMTimeVirtGetNano} */
626static DECLCALLBACK(uint64_t) pdmR0DevHlp_TMTimeVirtGetNano(PPDMDEVINS pDevIns)
627{
628 PDMDEV_ASSERT_DEVINS(pDevIns);
629 LogFlow(("pdmR0DevHlp_TMTimeVirtGetNano: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
630 return TMVirtualToNano(pDevIns->Internal.s.pGVM, TMVirtualGet(pDevIns->Internal.s.pGVM));
631}
632
633
634/** @interface_method_impl{PDMDEVHLPR0,pfnQueueToPtr} */
635static DECLCALLBACK(PPDMQUEUE) pdmR0DevHlp_QueueToPtr(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
636{
637 PDMDEV_ASSERT_DEVINS(pDevIns);
638 RT_NOREF(pDevIns);
639 return (PPDMQUEUE)MMHyperR3ToCC(pDevIns->Internal.s.pGVM, hQueue);
640}
641
642
643/** @interface_method_impl{PDMDEVHLPR0,pfnQueueAlloc} */
644static DECLCALLBACK(PPDMQUEUEITEMCORE) pdmR0DevHlp_QueueAlloc(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
645{
646 return PDMQueueAlloc(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue));
647}
648
649
650/** @interface_method_impl{PDMDEVHLPR0,pfnQueueInsert} */
651static DECLCALLBACK(void) pdmR0DevHlp_QueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)
652{
653 return PDMQueueInsert(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue), pItem);
654}
655
656
657/** @interface_method_impl{PDMDEVHLPR0,pfnQueueInsertEx} */
658static DECLCALLBACK(void) pdmR0DevHlp_QueueInsertEx(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem,
659 uint64_t cNanoMaxDelay)
660{
661 return PDMQueueInsertEx(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue), pItem, cNanoMaxDelay);
662}
663
664
665/** @interface_method_impl{PDMDEVHLPR0,pfnQueueFlushIfNecessary} */
666static DECLCALLBACK(bool) pdmR0DevHlp_QueueFlushIfNecessary(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
667{
668 return PDMQueueFlushIfNecessary(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue));
669}
670
671
672/** @interface_method_impl{PDMDEVHLPR0,pfnTaskTrigger} */
673static DECLCALLBACK(int) pdmR0DevHlp_TaskTrigger(PPDMDEVINS pDevIns, PDMTASKHANDLE hTask)
674{
675 PDMDEV_ASSERT_DEVINS(pDevIns);
676 LogFlow(("pdmR0DevHlp_TaskTrigger: caller='%s'/%d: hTask=%RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, hTask));
677
678 int rc = PDMTaskTrigger(pDevIns->Internal.s.pGVM, PDMTASKTYPE_DEV, pDevIns->pDevInsForR3, hTask);
679
680 LogFlow(("pdmR0DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
681 return rc;
682}
683
684
685/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventSignal} */
686static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventSignal(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
687{
688 PDMDEV_ASSERT_DEVINS(pDevIns);
689 LogFlow(("pdmR0DevHlp_SUPSemEventSignal: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
690
691 int rc = SUPSemEventSignal(pDevIns->Internal.s.pGVM->pSession, hEvent);
692
693 LogFlow(("pdmR0DevHlp_SUPSemEventSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
694 return rc;
695}
696
697
698/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventWaitNoResume} */
699static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint32_t cMillies)
700{
701 PDMDEV_ASSERT_DEVINS(pDevIns);
702 LogFlow(("pdmR0DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: hEvent=%p cNsTimeout=%RU32\n",
703 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cMillies));
704
705 int rc = SUPSemEventWaitNoResume(pDevIns->Internal.s.pGVM->pSession, hEvent, cMillies);
706
707 LogFlow(("pdmR0DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
708 return rc;
709}
710
711
712/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventWaitNsAbsIntr} */
713static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
714{
715 PDMDEV_ASSERT_DEVINS(pDevIns);
716 LogFlow(("pdmR0DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: hEvent=%p uNsTimeout=%RU64\n",
717 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, uNsTimeout));
718
719 int rc = SUPSemEventWaitNsAbsIntr(pDevIns->Internal.s.pGVM->pSession, hEvent, uNsTimeout);
720
721 LogFlow(("pdmR0DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
722 return rc;
723}
724
725
726/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventWaitNsRelIntr} */
727static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
728{
729 PDMDEV_ASSERT_DEVINS(pDevIns);
730 LogFlow(("pdmR0DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: hEvent=%p cNsTimeout=%RU64\n",
731 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cNsTimeout));
732
733 int rc = SUPSemEventWaitNsRelIntr(pDevIns->Internal.s.pGVM->pSession, hEvent, cNsTimeout);
734
735 LogFlow(("pdmR0DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
736 return rc;
737}
738
739
740/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventGetResolution} */
741static DECLCALLBACK(uint32_t) pdmR0DevHlp_SUPSemEventGetResolution(PPDMDEVINS pDevIns)
742{
743 PDMDEV_ASSERT_DEVINS(pDevIns);
744 LogFlow(("pdmR0DevHlp_SUPSemEventGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
745
746 uint32_t cNsResolution = SUPSemEventGetResolution(pDevIns->Internal.s.pGVM->pSession);
747
748 LogFlow(("pdmR0DevHlp_SUPSemEventGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
749 return cNsResolution;
750}
751
752
753/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiSignal} */
754static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiSignal(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
755{
756 PDMDEV_ASSERT_DEVINS(pDevIns);
757 LogFlow(("pdmR0DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
758
759 int rc = SUPSemEventMultiSignal(pDevIns->Internal.s.pGVM->pSession, hEventMulti);
760
761 LogFlow(("pdmR0DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
762 return rc;
763}
764
765
766/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiReset} */
767static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiReset(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
768{
769 PDMDEV_ASSERT_DEVINS(pDevIns);
770 LogFlow(("pdmR0DevHlp_SUPSemEventMultiReset: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
771
772 int rc = SUPSemEventMultiReset(pDevIns->Internal.s.pGVM->pSession, hEventMulti);
773
774 LogFlow(("pdmR0DevHlp_SUPSemEventMultiReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
775 return rc;
776}
777
778
779/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiWaitNoResume} */
780static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
781 uint32_t cMillies)
782{
783 PDMDEV_ASSERT_DEVINS(pDevIns);
784 LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: hEventMulti=%p cMillies=%RU32\n",
785 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cMillies));
786
787 int rc = SUPSemEventMultiWaitNoResume(pDevIns->Internal.s.pGVM->pSession, hEventMulti, cMillies);
788
789 LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
790 return rc;
791}
792
793
794/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiWaitNsAbsIntr} */
795static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
796 uint64_t uNsTimeout)
797{
798 PDMDEV_ASSERT_DEVINS(pDevIns);
799 LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: hEventMulti=%p uNsTimeout=%RU64\n",
800 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, uNsTimeout));
801
802 int rc = SUPSemEventMultiWaitNsAbsIntr(pDevIns->Internal.s.pGVM->pSession, hEventMulti, uNsTimeout);
803
804 LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
805 return rc;
806}
807
808
809/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiWaitNsRelIntr} */
810static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
811 uint64_t cNsTimeout)
812{
813 PDMDEV_ASSERT_DEVINS(pDevIns);
814 LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: hEventMulti=%p cNsTimeout=%RU64\n",
815 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cNsTimeout));
816
817 int rc = SUPSemEventMultiWaitNsRelIntr(pDevIns->Internal.s.pGVM->pSession, hEventMulti, cNsTimeout);
818
819 LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
820 return rc;
821}
822
823
824/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiGetResolution} */
825static DECLCALLBACK(uint32_t) pdmR0DevHlp_SUPSemEventMultiGetResolution(PPDMDEVINS pDevIns)
826{
827 PDMDEV_ASSERT_DEVINS(pDevIns);
828 LogFlow(("pdmR0DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
829
830 uint32_t cNsResolution = SUPSemEventMultiGetResolution(pDevIns->Internal.s.pGVM->pSession);
831
832 LogFlow(("pdmR0DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
833 return cNsResolution;
834}
835
836
837/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectGetNop} */
838static DECLCALLBACK(PPDMCRITSECT) pdmR0DevHlp_CritSectGetNop(PPDMDEVINS pDevIns)
839{
840 PDMDEV_ASSERT_DEVINS(pDevIns);
841 PGVM pGVM = pDevIns->Internal.s.pGVM;
842
843 PPDMCRITSECT pCritSect = &pGVM->pdm.s.NopCritSect;
844 LogFlow(("pdmR0DevHlp_CritSectGetNop: caller='%s'/%d: return %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
845 return pCritSect;
846}
847
848
849/** @interface_method_impl{PDMDEVHLPR0,pfnSetDeviceCritSect} */
850static DECLCALLBACK(int) pdmR0DevHlp_SetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
851{
852 /*
853 * Validate input.
854 *
855 * Note! We only allow the automatically created default critical section
856 * to be replaced by this API.
857 */
858 PDMDEV_ASSERT_DEVINS(pDevIns);
859 AssertPtrReturn(pCritSect, VERR_INVALID_POINTER);
860 LogFlow(("pdmR0DevHlp_SetDeviceCritSect: caller='%s'/%d: pCritSect=%p (%s)\n",
861 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pCritSect->s.pszName));
862 AssertReturn(PDMCritSectIsInitialized(pCritSect), VERR_INVALID_PARAMETER);
863 PGVM pGVM = pDevIns->Internal.s.pGVM;
864 AssertReturn(pCritSect->s.pVMR0 == pGVM, VERR_INVALID_PARAMETER);
865
866 VM_ASSERT_EMT(pGVM);
867 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
868
869 /*
870 * Check that ring-3 has already done this, then effect the change.
871 */
872 AssertReturn(pDevIns->pDevInsForR3R0->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_CHANGED_CRITSECT, VERR_WRONG_ORDER);
873 pDevIns->pCritSectRoR0 = pCritSect;
874
875 LogFlow(("pdmR0DevHlp_SetDeviceCritSect: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
876 return VINF_SUCCESS;
877}
878
879
880/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectEnter} */
881static DECLCALLBACK(int) pdmR0DevHlp_CritSectEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy)
882{
883 PDMDEV_ASSERT_DEVINS(pDevIns);
884 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pGVM to the crit sect code. */
885 return PDMCritSectEnter(pCritSect, rcBusy);
886}
887
888
889/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectEnterDebug} */
890static DECLCALLBACK(int) pdmR0DevHlp_CritSectEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
891{
892 PDMDEV_ASSERT_DEVINS(pDevIns);
893 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pGVM to the crit sect code. */
894 return PDMCritSectEnterDebug(pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
895}
896
897
898/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectTryEnter} */
899static DECLCALLBACK(int) pdmR0DevHlp_CritSectTryEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
900{
901 PDMDEV_ASSERT_DEVINS(pDevIns);
902 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pGVM to the crit sect code. */
903 return PDMCritSectTryEnter(pCritSect);
904}
905
906
907/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectTryEnterDebug} */
908static DECLCALLBACK(int) pdmR0DevHlp_CritSectTryEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
909{
910 PDMDEV_ASSERT_DEVINS(pDevIns);
911 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pGVM to the crit sect code. */
912 return PDMCritSectTryEnterDebug(pCritSect, uId, RT_SRC_POS_ARGS);
913}
914
915
916/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectLeave} */
917static DECLCALLBACK(int) pdmR0DevHlp_CritSectLeave(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
918{
919 PDMDEV_ASSERT_DEVINS(pDevIns);
920 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pGVM to the crit sect code. */
921 return PDMCritSectLeave(pCritSect);
922}
923
924
925/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectIsOwner} */
926static DECLCALLBACK(bool) pdmR0DevHlp_CritSectIsOwner(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
927{
928 PDMDEV_ASSERT_DEVINS(pDevIns);
929 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pGVM to the crit sect code. */
930 return PDMCritSectIsOwner(pCritSect);
931}
932
933
934/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectIsInitialized} */
935static DECLCALLBACK(bool) pdmR0DevHlp_CritSectIsInitialized(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
936{
937 PDMDEV_ASSERT_DEVINS(pDevIns);
938 RT_NOREF(pDevIns);
939 return PDMCritSectIsInitialized(pCritSect);
940}
941
942
943/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectHasWaiters} */
944static DECLCALLBACK(bool) pdmR0DevHlp_CritSectHasWaiters(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
945{
946 PDMDEV_ASSERT_DEVINS(pDevIns);
947 RT_NOREF(pDevIns);
948 return PDMCritSectHasWaiters(pCritSect);
949}
950
951
952/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectGetRecursion} */
953static DECLCALLBACK(uint32_t) pdmR0DevHlp_CritSectGetRecursion(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
954{
955 PDMDEV_ASSERT_DEVINS(pDevIns);
956 RT_NOREF(pDevIns);
957 return PDMCritSectGetRecursion(pCritSect);
958}
959
960
961/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectScheduleExitEvent} */
962static DECLCALLBACK(int) pdmR0DevHlp_CritSectScheduleExitEvent(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect,
963 SUPSEMEVENT hEventToSignal)
964{
965 PDMDEV_ASSERT_DEVINS(pDevIns);
966 RT_NOREF(pDevIns);
967 return PDMHCCritSectScheduleExitEvent(pCritSect, hEventToSignal);
968}
969
970
971/** @interface_method_impl{PDMDEVHLPR0,pfnDBGFTraceBuf} */
972static DECLCALLBACK(RTTRACEBUF) pdmR0DevHlp_DBGFTraceBuf(PPDMDEVINS pDevIns)
973{
974 PDMDEV_ASSERT_DEVINS(pDevIns);
975 RTTRACEBUF hTraceBuf = pDevIns->Internal.s.pGVM->hTraceBufR0;
976 LogFlow(("pdmR0DevHlp_DBGFTraceBuf: caller='%p'/%d: returns %p\n", pDevIns, pDevIns->iInstance, hTraceBuf));
977 return hTraceBuf;
978}
979
980
981/** @interface_method_impl{PDMDEVHLPR0,pfnPCIBusSetUpContext} */
982static DECLCALLBACK(int) pdmR0DevHlp_PCIBusSetUpContext(PPDMDEVINS pDevIns, PPDMPCIBUSREGR0 pPciBusReg, PCPDMPCIHLPR0 *ppPciHlp)
983{
984 PDMDEV_ASSERT_DEVINS(pDevIns);
985 LogFlow(("pdmR0DevHlp_PCIBusSetUpContext: caller='%p'/%d: pPciBusReg=%p{.u32Version=%#x, .iBus=%#u, .pfnSetIrq=%p, u32EnvVersion=%#x} ppPciHlp=%p\n",
986 pDevIns, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->iBus, pPciBusReg->pfnSetIrq,
987 pPciBusReg->u32EndVersion, ppPciHlp));
988 PGVM pGVM = pDevIns->Internal.s.pGVM;
989
990 /*
991 * Validate input.
992 */
993 AssertPtrReturn(pPciBusReg, VERR_INVALID_POINTER);
994 AssertLogRelMsgReturn(pPciBusReg->u32Version == PDM_PCIBUSREGCC_VERSION,
995 ("%#x vs %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGCC_VERSION), VERR_VERSION_MISMATCH);
996 AssertPtrReturn(pPciBusReg->pfnSetIrq, VERR_INVALID_POINTER);
997 AssertLogRelMsgReturn(pPciBusReg->u32EndVersion == PDM_PCIBUSREGCC_VERSION,
998 ("%#x vs %#x\n", pPciBusReg->u32EndVersion, PDM_PCIBUSREGCC_VERSION), VERR_VERSION_MISMATCH);
999
1000 AssertPtrReturn(ppPciHlp, VERR_INVALID_POINTER);
1001
1002 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1003 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
1004
1005 /* Check the shared bus data (registered earlier from ring-3): */
1006 uint32_t iBus = pPciBusReg->iBus;
1007 ASMCompilerBarrier();
1008 AssertLogRelMsgReturn(iBus < RT_ELEMENTS(pGVM->pdm.s.aPciBuses), ("iBus=%#x\n", iBus), VERR_OUT_OF_RANGE);
1009 PPDMPCIBUS pPciBusShared = &pGVM->pdm.s.aPciBuses[iBus];
1010 AssertLogRelMsgReturn(pPciBusShared->iBus == iBus, ("%u vs %u\n", pPciBusShared->iBus, iBus), VERR_INVALID_PARAMETER);
1011 AssertLogRelMsgReturn(pPciBusShared->pDevInsR3 == pDevIns->pDevInsForR3,
1012 ("%p vs %p (iBus=%u)\n", pPciBusShared->pDevInsR3, pDevIns->pDevInsForR3, iBus), VERR_NOT_OWNER);
1013
1014 /* Check that the bus isn't already registered in ring-0: */
1015 AssertCompile(RT_ELEMENTS(pGVM->pdm.s.aPciBuses) == RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses));
1016 PPDMPCIBUSR0 pPciBusR0 = &pGVM->pdmr0.s.aPciBuses[iBus];
1017 AssertLogRelMsgReturn(pPciBusR0->pDevInsR0 == NULL,
1018 ("%p (caller pDevIns=%p, iBus=%u)\n", pPciBusR0->pDevInsR0, pDevIns, iBus),
1019 VERR_ALREADY_EXISTS);
1020
1021 /*
1022 * Do the registering.
1023 */
1024 pPciBusR0->iBus = iBus;
1025 pPciBusR0->uPadding0 = 0xbeefbeef;
1026 pPciBusR0->pfnSetIrqR0 = pPciBusReg->pfnSetIrq;
1027 pPciBusR0->pDevInsR0 = pDevIns;
1028
1029 *ppPciHlp = &g_pdmR0PciHlp;
1030
1031 LogFlow(("pdmR0DevHlp_PCIBusSetUpContext: caller='%p'/%d: returns VINF_SUCCESS\n", pDevIns, pDevIns->iInstance));
1032 return VINF_SUCCESS;
1033}
1034
1035
1036/** @interface_method_impl{PDMDEVHLPR0,pfnIommuSetUpContext} */
1037static DECLCALLBACK(int) pdmR0DevHlp_IommuSetUpContext(PPDMDEVINS pDevIns, PPDMIOMMUREGR0 pIommuReg, PCPDMIOMMUHLPR0 *ppIommuHlp)
1038{
1039 PDMDEV_ASSERT_DEVINS(pDevIns);
1040 LogFlow(("pdmR0DevHlp_IommuSetUpContext: caller='%p'/%d: pIommuReg=%p{.u32Version=%#x, u32TheEnd=%#x} ppIommuHlp=%p\n",
1041 pDevIns, pDevIns->iInstance, pIommuReg, pIommuReg->u32Version, pIommuReg->u32TheEnd, ppIommuHlp));
1042 PGVM pGVM = pDevIns->Internal.s.pGVM;
1043
1044 /*
1045 * Validate input.
1046 */
1047 AssertPtrReturn(pIommuReg, VERR_INVALID_POINTER);
1048 AssertLogRelMsgReturn(pIommuReg->u32Version == PDM_IOMMUREGCC_VERSION,
1049 ("%#x vs %#x\n", pIommuReg->u32Version, PDM_IOMMUREGCC_VERSION), VERR_VERSION_MISMATCH);
1050 AssertLogRelMsgReturn(pIommuReg->u32TheEnd == PDM_IOMMUREGCC_VERSION,
1051 ("%#x vs %#x\n", pIommuReg->u32TheEnd, PDM_IOMMUREGCC_VERSION), VERR_VERSION_MISMATCH);
1052
1053 AssertPtrReturn(ppIommuHlp, VERR_INVALID_POINTER);
1054
1055 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1056 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
1057
1058 /* Check the IOMMU shared data (registered earlier from ring-3). */
1059 uint32_t const idxIommu = pIommuReg->idxIommu;
1060 ASMCompilerBarrier();
1061 AssertLogRelMsgReturn(idxIommu < RT_ELEMENTS(pGVM->pdm.s.aIommus), ("idxIommu=%#x\n", idxIommu), VERR_OUT_OF_RANGE);
1062 PPDMIOMMU pIommuShared = &pGVM->pdm.s.aIommus[idxIommu];
1063 AssertLogRelMsgReturn(pIommuShared->idxIommu == idxIommu, ("%u vs %u\n", pIommuShared->idxIommu, idxIommu), VERR_INVALID_PARAMETER);
1064 AssertLogRelMsgReturn(pIommuShared->pDevInsR3 == pDevIns->pDevInsForR3,
1065 ("%p vs %p (idxIommu=%u)\n", pIommuShared->pDevInsR3, pDevIns->pDevInsForR3, idxIommu), VERR_NOT_OWNER);
1066
1067 /* Check that the IOMMU isn't already registered in ring-0. */
1068 AssertCompile(RT_ELEMENTS(pGVM->pdm.s.aIommus) == RT_ELEMENTS(pGVM->pdmr0.s.aIommus));
1069 PPDMIOMMUR0 pIommuR0 = &pGVM->pdmr0.s.aIommus[idxIommu];
1070 AssertLogRelMsgReturn(pIommuR0->pDevInsR0 == NULL,
1071 ("%p (caller pDevIns=%p, idxIommu=%u)\n", pIommuR0->pDevInsR0, pDevIns, idxIommu),
1072 VERR_ALREADY_EXISTS);
1073
1074 /*
1075 * Register.
1076 */
1077 pIommuR0->idxIommu = idxIommu;
1078 pIommuR0->uPadding0 = 0xdeaddead;
1079 pIommuR0->pDevInsR0 = pDevIns;
1080
1081 *ppIommuHlp = &g_pdmR0IommuHlp;
1082
1083 LogFlow(("pdmR0DevHlp_IommuSetUpContext: caller='%p'/%d: returns VINF_SUCCESS\n", pDevIns, pDevIns->iInstance));
1084 return VINF_SUCCESS;
1085}
1086
1087
1088/** @interface_method_impl{PDMDEVHLPR0,pfnPICSetUpContext} */
1089static DECLCALLBACK(int) pdmR0DevHlp_PICSetUpContext(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp)
1090{
1091 PDMDEV_ASSERT_DEVINS(pDevIns);
1092 LogFlow(("pdmR0DevHlp_PICSetUpContext: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnGetInterrupt=%p, .u32TheEnd=%#x } ppPicHlp=%p\n",
1093 pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrq, pPicReg->pfnGetInterrupt, pPicReg->u32TheEnd, ppPicHlp));
1094 PGVM pGVM = pDevIns->Internal.s.pGVM;
1095
1096 /*
1097 * Validate input.
1098 */
1099 AssertMsgReturn(pPicReg->u32Version == PDM_PICREG_VERSION,
1100 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32Version, PDM_PICREG_VERSION),
1101 VERR_VERSION_MISMATCH);
1102 AssertPtrReturn(pPicReg->pfnSetIrq, VERR_INVALID_POINTER);
1103 AssertPtrReturn(pPicReg->pfnGetInterrupt, VERR_INVALID_POINTER);
1104 AssertMsgReturn(pPicReg->u32TheEnd == PDM_PICREG_VERSION,
1105 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32TheEnd, PDM_PICREG_VERSION),
1106 VERR_VERSION_MISMATCH);
1107 AssertPtrReturn(ppPicHlp, VERR_INVALID_POINTER);
1108
1109 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1110 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
1111
1112 /* Check that it's the same device as made the ring-3 registrations: */
1113 AssertLogRelMsgReturn(pGVM->pdm.s.Pic.pDevInsR3 == pDevIns->pDevInsForR3,
1114 ("%p vs %p\n", pGVM->pdm.s.Pic.pDevInsR3, pDevIns->pDevInsForR3), VERR_NOT_OWNER);
1115
1116 /* Check that it isn't already registered in ring-0: */
1117 AssertLogRelMsgReturn(pGVM->pdm.s.Pic.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.Pic.pDevInsR0, pDevIns),
1118 VERR_ALREADY_EXISTS);
1119
1120 /*
1121 * Take down the callbacks and instance.
1122 */
1123 pGVM->pdm.s.Pic.pDevInsR0 = pDevIns;
1124 pGVM->pdm.s.Pic.pfnSetIrqR0 = pPicReg->pfnSetIrq;
1125 pGVM->pdm.s.Pic.pfnGetInterruptR0 = pPicReg->pfnGetInterrupt;
1126 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
1127
1128 /* set the helper pointer and return. */
1129 *ppPicHlp = &g_pdmR0PicHlp;
1130 LogFlow(("pdmR0DevHlp_PICSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
1131 return VINF_SUCCESS;
1132}
1133
1134
1135/** @interface_method_impl{PDMDEVHLPR0,pfnApicSetUpContext} */
1136static DECLCALLBACK(int) pdmR0DevHlp_ApicSetUpContext(PPDMDEVINS pDevIns)
1137{
1138 PDMDEV_ASSERT_DEVINS(pDevIns);
1139 LogFlow(("pdmR0DevHlp_ApicSetUpContext: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
1140 PGVM pGVM = pDevIns->Internal.s.pGVM;
1141
1142 /*
1143 * Validate input.
1144 */
1145 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1146 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
1147
1148 /* Check that it's the same device as made the ring-3 registrations: */
1149 AssertLogRelMsgReturn(pGVM->pdm.s.Apic.pDevInsR3 == pDevIns->pDevInsForR3,
1150 ("%p vs %p\n", pGVM->pdm.s.Apic.pDevInsR3, pDevIns->pDevInsForR3), VERR_NOT_OWNER);
1151
1152 /* Check that it isn't already registered in ring-0: */
1153 AssertLogRelMsgReturn(pGVM->pdm.s.Apic.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.Apic.pDevInsR0, pDevIns),
1154 VERR_ALREADY_EXISTS);
1155
1156 /*
1157 * Take down the instance.
1158 */
1159 pGVM->pdm.s.Apic.pDevInsR0 = pDevIns;
1160 Log(("PDM: Registered APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
1161
1162 /* set the helper pointer and return. */
1163 LogFlow(("pdmR0DevHlp_ApicSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
1164 return VINF_SUCCESS;
1165}
1166
1167
1168/** @interface_method_impl{PDMDEVHLPR0,pfnIoApicSetUpContext} */
1169static DECLCALLBACK(int) pdmR0DevHlp_IoApicSetUpContext(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
1170{
1171 PDMDEV_ASSERT_DEVINS(pDevIns);
1172 LogFlow(("pdmR0DevHlp_IoApicSetUpContext: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnSendMsi=%p, .pfnSetEoi=%p, .u32TheEnd=%#x } ppIoApicHlp=%p\n",
1173 pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrq, pIoApicReg->pfnSendMsi, pIoApicReg->pfnSetEoi, pIoApicReg->u32TheEnd, ppIoApicHlp));
1174 PGVM pGVM = pDevIns->Internal.s.pGVM;
1175
1176 /*
1177 * Validate input.
1178 */
1179 AssertMsgReturn(pIoApicReg->u32Version == PDM_IOAPICREG_VERSION,
1180 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32Version, PDM_IOAPICREG_VERSION),
1181 VERR_VERSION_MISMATCH);
1182 AssertPtrReturn(pIoApicReg->pfnSetIrq, VERR_INVALID_POINTER);
1183 AssertPtrReturn(pIoApicReg->pfnSendMsi, VERR_INVALID_POINTER);
1184 AssertPtrReturn(pIoApicReg->pfnSetEoi, VERR_INVALID_POINTER);
1185 AssertMsgReturn(pIoApicReg->u32TheEnd == PDM_IOAPICREG_VERSION,
1186 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32TheEnd, PDM_IOAPICREG_VERSION),
1187 VERR_VERSION_MISMATCH);
1188 AssertPtrReturn(ppIoApicHlp, VERR_INVALID_POINTER);
1189
1190 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1191 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
1192
1193 /* Check that it's the same device as made the ring-3 registrations: */
1194 AssertLogRelMsgReturn(pGVM->pdm.s.IoApic.pDevInsR3 == pDevIns->pDevInsForR3,
1195 ("%p vs %p\n", pGVM->pdm.s.IoApic.pDevInsR3, pDevIns->pDevInsForR3), VERR_NOT_OWNER);
1196
1197 /* Check that it isn't already registered in ring-0: */
1198 AssertLogRelMsgReturn(pGVM->pdm.s.IoApic.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.IoApic.pDevInsR0, pDevIns),
1199 VERR_ALREADY_EXISTS);
1200
1201 /*
1202 * Take down the callbacks and instance.
1203 */
1204 pGVM->pdm.s.IoApic.pDevInsR0 = pDevIns;
1205 pGVM->pdm.s.IoApic.pfnSetIrqR0 = pIoApicReg->pfnSetIrq;
1206 pGVM->pdm.s.IoApic.pfnSendMsiR0 = pIoApicReg->pfnSendMsi;
1207 pGVM->pdm.s.IoApic.pfnSetEoiR0 = pIoApicReg->pfnSetEoi;
1208 Log(("PDM: Registered IOAPIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
1209
1210 /* set the helper pointer and return. */
1211 *ppIoApicHlp = &g_pdmR0IoApicHlp;
1212 LogFlow(("pdmR0DevHlp_IoApicSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
1213 return VINF_SUCCESS;
1214}
1215
1216
1217/** @interface_method_impl{PDMDEVHLPR0,pfnHpetSetUpContext} */
1218static DECLCALLBACK(int) pdmR0DevHlp_HpetSetUpContext(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR0 *ppHpetHlp)
1219{
1220 PDMDEV_ASSERT_DEVINS(pDevIns);
1221 LogFlow(("pdmR0DevHlp_HpetSetUpContext: caller='%s'/%d: pHpetReg=%p:{.u32Version=%#x, } ppHpetHlp=%p\n",
1222 pDevIns->pReg->szName, pDevIns->iInstance, pHpetReg, pHpetReg->u32Version, ppHpetHlp));
1223 PGVM pGVM = pDevIns->Internal.s.pGVM;
1224
1225 /*
1226 * Validate input.
1227 */
1228 AssertMsgReturn(pHpetReg->u32Version == PDM_HPETREG_VERSION,
1229 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pHpetReg->u32Version, PDM_HPETREG_VERSION),
1230 VERR_VERSION_MISMATCH);
1231 AssertPtrReturn(ppHpetHlp, VERR_INVALID_POINTER);
1232
1233 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1234 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
1235
1236 /* Check that it's the same device as made the ring-3 registrations: */
1237 AssertLogRelMsgReturn(pGVM->pdm.s.pHpet == pDevIns->pDevInsForR3, ("%p vs %p\n", pGVM->pdm.s.pHpet, pDevIns->pDevInsForR3),
1238 VERR_NOT_OWNER);
1239
1240 ///* Check that it isn't already registered in ring-0: */
1241 //AssertLogRelMsgReturn(pGVM->pdm.s.Hpet.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.Hpet.pDevInsR0, pDevIns),
1242 // VERR_ALREADY_EXISTS);
1243
1244 /*
1245 * Nothing to take down here at present.
1246 */
1247 Log(("PDM: Registered HPET device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
1248
1249 /* set the helper pointer and return. */
1250 *ppHpetHlp = &g_pdmR0HpetHlp;
1251 LogFlow(("pdmR0DevHlp_HpetSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
1252 return VINF_SUCCESS;
1253}
1254
1255
1256/**
1257 * The Ring-0 Device Helper Callbacks.
1258 */
1259extern DECLEXPORT(const PDMDEVHLPR0) g_pdmR0DevHlp =
1260{
1261 PDM_DEVHLPR0_VERSION,
1262 pdmR0DevHlp_IoPortSetUpContextEx,
1263 pdmR0DevHlp_MmioSetUpContextEx,
1264 pdmR0DevHlp_Mmio2SetUpContext,
1265 pdmR0DevHlp_PCIPhysRead,
1266 pdmR0DevHlp_PCIPhysWrite,
1267 pdmR0DevHlp_PCISetIrq,
1268 pdmR0DevHlp_ISASetIrq,
1269 pdmR0DevHlp_PhysRead,
1270 pdmR0DevHlp_PhysWrite,
1271 pdmR0DevHlp_A20IsEnabled,
1272 pdmR0DevHlp_VMState,
1273 pdmR0DevHlp_VMSetError,
1274 pdmR0DevHlp_VMSetErrorV,
1275 pdmR0DevHlp_VMSetRuntimeError,
1276 pdmR0DevHlp_VMSetRuntimeErrorV,
1277 pdmR0DevHlp_GetVM,
1278 pdmR0DevHlp_GetVMCPU,
1279 pdmR0DevHlp_GetCurrentCpuId,
1280 pdmR0DevHlp_TimerToPtr,
1281 pdmR0DevHlp_TimerFromMicro,
1282 pdmR0DevHlp_TimerFromMilli,
1283 pdmR0DevHlp_TimerFromNano,
1284 pdmR0DevHlp_TimerGet,
1285 pdmR0DevHlp_TimerGetFreq,
1286 pdmR0DevHlp_TimerGetNano,
1287 pdmR0DevHlp_TimerIsActive,
1288 pdmR0DevHlp_TimerIsLockOwner,
1289 pdmR0DevHlp_TimerLockClock,
1290 pdmR0DevHlp_TimerLockClock2,
1291 pdmR0DevHlp_TimerSet,
1292 pdmR0DevHlp_TimerSetFrequencyHint,
1293 pdmR0DevHlp_TimerSetMicro,
1294 pdmR0DevHlp_TimerSetMillies,
1295 pdmR0DevHlp_TimerSetNano,
1296 pdmR0DevHlp_TimerSetRelative,
1297 pdmR0DevHlp_TimerStop,
1298 pdmR0DevHlp_TimerUnlockClock,
1299 pdmR0DevHlp_TimerUnlockClock2,
1300 pdmR0DevHlp_TMTimeVirtGet,
1301 pdmR0DevHlp_TMTimeVirtGetFreq,
1302 pdmR0DevHlp_TMTimeVirtGetNano,
1303 pdmR0DevHlp_QueueToPtr,
1304 pdmR0DevHlp_QueueAlloc,
1305 pdmR0DevHlp_QueueInsert,
1306 pdmR0DevHlp_QueueInsertEx,
1307 pdmR0DevHlp_QueueFlushIfNecessary,
1308 pdmR0DevHlp_TaskTrigger,
1309 pdmR0DevHlp_SUPSemEventSignal,
1310 pdmR0DevHlp_SUPSemEventWaitNoResume,
1311 pdmR0DevHlp_SUPSemEventWaitNsAbsIntr,
1312 pdmR0DevHlp_SUPSemEventWaitNsRelIntr,
1313 pdmR0DevHlp_SUPSemEventGetResolution,
1314 pdmR0DevHlp_SUPSemEventMultiSignal,
1315 pdmR0DevHlp_SUPSemEventMultiReset,
1316 pdmR0DevHlp_SUPSemEventMultiWaitNoResume,
1317 pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr,
1318 pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr,
1319 pdmR0DevHlp_SUPSemEventMultiGetResolution,
1320 pdmR0DevHlp_CritSectGetNop,
1321 pdmR0DevHlp_SetDeviceCritSect,
1322 pdmR0DevHlp_CritSectEnter,
1323 pdmR0DevHlp_CritSectEnterDebug,
1324 pdmR0DevHlp_CritSectTryEnter,
1325 pdmR0DevHlp_CritSectTryEnterDebug,
1326 pdmR0DevHlp_CritSectLeave,
1327 pdmR0DevHlp_CritSectIsOwner,
1328 pdmR0DevHlp_CritSectIsInitialized,
1329 pdmR0DevHlp_CritSectHasWaiters,
1330 pdmR0DevHlp_CritSectGetRecursion,
1331 pdmR0DevHlp_CritSectScheduleExitEvent,
1332 pdmR0DevHlp_DBGFTraceBuf,
1333 pdmR0DevHlp_PCIBusSetUpContext,
1334 pdmR0DevHlp_IommuSetUpContext,
1335 pdmR0DevHlp_PICSetUpContext,
1336 pdmR0DevHlp_ApicSetUpContext,
1337 pdmR0DevHlp_IoApicSetUpContext,
1338 pdmR0DevHlp_HpetSetUpContext,
1339 NULL /*pfnReserved1*/,
1340 NULL /*pfnReserved2*/,
1341 NULL /*pfnReserved3*/,
1342 NULL /*pfnReserved4*/,
1343 NULL /*pfnReserved5*/,
1344 NULL /*pfnReserved6*/,
1345 NULL /*pfnReserved7*/,
1346 NULL /*pfnReserved8*/,
1347 NULL /*pfnReserved9*/,
1348 NULL /*pfnReserved10*/,
1349 PDM_DEVHLPR0_VERSION
1350};
1351
1352
1353#ifdef VBOX_WITH_DBGF_TRACING
1354/**
1355 * The Ring-0 Device Helper Callbacks - tracing variant.
1356 */
1357extern DECLEXPORT(const PDMDEVHLPR0) g_pdmR0DevHlpTracing =
1358{
1359 PDM_DEVHLPR0_VERSION,
1360 pdmR0DevHlpTracing_IoPortSetUpContextEx,
1361 pdmR0DevHlpTracing_MmioSetUpContextEx,
1362 pdmR0DevHlp_Mmio2SetUpContext,
1363 pdmR0DevHlpTracing_PCIPhysRead,
1364 pdmR0DevHlpTracing_PCIPhysWrite,
1365 pdmR0DevHlpTracing_PCISetIrq,
1366 pdmR0DevHlpTracing_ISASetIrq,
1367 pdmR0DevHlp_PhysRead,
1368 pdmR0DevHlp_PhysWrite,
1369 pdmR0DevHlp_A20IsEnabled,
1370 pdmR0DevHlp_VMState,
1371 pdmR0DevHlp_VMSetError,
1372 pdmR0DevHlp_VMSetErrorV,
1373 pdmR0DevHlp_VMSetRuntimeError,
1374 pdmR0DevHlp_VMSetRuntimeErrorV,
1375 pdmR0DevHlp_GetVM,
1376 pdmR0DevHlp_GetVMCPU,
1377 pdmR0DevHlp_GetCurrentCpuId,
1378 pdmR0DevHlp_TimerToPtr,
1379 pdmR0DevHlp_TimerFromMicro,
1380 pdmR0DevHlp_TimerFromMilli,
1381 pdmR0DevHlp_TimerFromNano,
1382 pdmR0DevHlp_TimerGet,
1383 pdmR0DevHlp_TimerGetFreq,
1384 pdmR0DevHlp_TimerGetNano,
1385 pdmR0DevHlp_TimerIsActive,
1386 pdmR0DevHlp_TimerIsLockOwner,
1387 pdmR0DevHlp_TimerLockClock,
1388 pdmR0DevHlp_TimerLockClock2,
1389 pdmR0DevHlp_TimerSet,
1390 pdmR0DevHlp_TimerSetFrequencyHint,
1391 pdmR0DevHlp_TimerSetMicro,
1392 pdmR0DevHlp_TimerSetMillies,
1393 pdmR0DevHlp_TimerSetNano,
1394 pdmR0DevHlp_TimerSetRelative,
1395 pdmR0DevHlp_TimerStop,
1396 pdmR0DevHlp_TimerUnlockClock,
1397 pdmR0DevHlp_TimerUnlockClock2,
1398 pdmR0DevHlp_TMTimeVirtGet,
1399 pdmR0DevHlp_TMTimeVirtGetFreq,
1400 pdmR0DevHlp_TMTimeVirtGetNano,
1401 pdmR0DevHlp_QueueToPtr,
1402 pdmR0DevHlp_QueueAlloc,
1403 pdmR0DevHlp_QueueInsert,
1404 pdmR0DevHlp_QueueInsertEx,
1405 pdmR0DevHlp_QueueFlushIfNecessary,
1406 pdmR0DevHlp_TaskTrigger,
1407 pdmR0DevHlp_SUPSemEventSignal,
1408 pdmR0DevHlp_SUPSemEventWaitNoResume,
1409 pdmR0DevHlp_SUPSemEventWaitNsAbsIntr,
1410 pdmR0DevHlp_SUPSemEventWaitNsRelIntr,
1411 pdmR0DevHlp_SUPSemEventGetResolution,
1412 pdmR0DevHlp_SUPSemEventMultiSignal,
1413 pdmR0DevHlp_SUPSemEventMultiReset,
1414 pdmR0DevHlp_SUPSemEventMultiWaitNoResume,
1415 pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr,
1416 pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr,
1417 pdmR0DevHlp_SUPSemEventMultiGetResolution,
1418 pdmR0DevHlp_CritSectGetNop,
1419 pdmR0DevHlp_SetDeviceCritSect,
1420 pdmR0DevHlp_CritSectEnter,
1421 pdmR0DevHlp_CritSectEnterDebug,
1422 pdmR0DevHlp_CritSectTryEnter,
1423 pdmR0DevHlp_CritSectTryEnterDebug,
1424 pdmR0DevHlp_CritSectLeave,
1425 pdmR0DevHlp_CritSectIsOwner,
1426 pdmR0DevHlp_CritSectIsInitialized,
1427 pdmR0DevHlp_CritSectHasWaiters,
1428 pdmR0DevHlp_CritSectGetRecursion,
1429 pdmR0DevHlp_CritSectScheduleExitEvent,
1430 pdmR0DevHlp_DBGFTraceBuf,
1431 pdmR0DevHlp_PCIBusSetUpContext,
1432 pdmR0DevHlp_IommuSetUpContext,
1433 pdmR0DevHlp_PICSetUpContext,
1434 pdmR0DevHlp_ApicSetUpContext,
1435 pdmR0DevHlp_IoApicSetUpContext,
1436 pdmR0DevHlp_HpetSetUpContext,
1437 NULL /*pfnReserved1*/,
1438 NULL /*pfnReserved2*/,
1439 NULL /*pfnReserved3*/,
1440 NULL /*pfnReserved4*/,
1441 NULL /*pfnReserved5*/,
1442 NULL /*pfnReserved6*/,
1443 NULL /*pfnReserved7*/,
1444 NULL /*pfnReserved8*/,
1445 NULL /*pfnReserved9*/,
1446 NULL /*pfnReserved10*/,
1447 PDM_DEVHLPR0_VERSION
1448};
1449#endif
1450
1451
1452/** @} */
1453
1454
1455/** @name PIC Ring-0 Helpers
1456 * @{
1457 */
1458
1459/** @interface_method_impl{PDMPICHLP,pfnSetInterruptFF} */
1460static DECLCALLBACK(void) pdmR0PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
1461{
1462 PDMDEV_ASSERT_DEVINS(pDevIns);
1463 PGVM pGVM = (PGVM)pDevIns->Internal.s.pGVM;
1464 PVMCPUCC pVCpu = &pGVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
1465 /** @todo r=ramshankar: Propagating rcRZ and make all callers handle it? */
1466 APICLocalInterrupt(pVCpu, 0 /* u8Pin */, 1 /* u8Level */, VINF_SUCCESS /* rcRZ */);
1467}
1468
1469
1470/** @interface_method_impl{PDMPICHLP,pfnClearInterruptFF} */
1471static DECLCALLBACK(void) pdmR0PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
1472{
1473 PDMDEV_ASSERT_DEVINS(pDevIns);
1474 PGVM pGVM = (PGVM)pDevIns->Internal.s.pGVM;
1475 PVMCPUCC pVCpu = &pGVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
1476 /** @todo r=ramshankar: Propagating rcRZ and make all callers handle it? */
1477 APICLocalInterrupt(pVCpu, 0 /* u8Pin */, 0 /* u8Level */, VINF_SUCCESS /* rcRZ */);
1478}
1479
1480
1481/** @interface_method_impl{PDMPICHLP,pfnLock} */
1482static DECLCALLBACK(int) pdmR0PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
1483{
1484 PDMDEV_ASSERT_DEVINS(pDevIns);
1485 return pdmLockEx(pDevIns->Internal.s.pGVM, rc);
1486}
1487
1488
1489/** @interface_method_impl{PDMPICHLP,pfnUnlock} */
1490static DECLCALLBACK(void) pdmR0PicHlp_Unlock(PPDMDEVINS pDevIns)
1491{
1492 PDMDEV_ASSERT_DEVINS(pDevIns);
1493 pdmUnlock(pDevIns->Internal.s.pGVM);
1494}
1495
1496
1497/**
1498 * The Ring-0 PIC Helper Callbacks.
1499 */
1500extern DECLEXPORT(const PDMPICHLP) g_pdmR0PicHlp =
1501{
1502 PDM_PICHLP_VERSION,
1503 pdmR0PicHlp_SetInterruptFF,
1504 pdmR0PicHlp_ClearInterruptFF,
1505 pdmR0PicHlp_Lock,
1506 pdmR0PicHlp_Unlock,
1507 PDM_PICHLP_VERSION
1508};
1509
1510/** @} */
1511
1512
1513/** @name I/O APIC Ring-0 Helpers
1514 * @{
1515 */
1516
1517/** @interface_method_impl{PDMIOAPICHLP,pfnApicBusDeliver} */
1518static DECLCALLBACK(int) pdmR0IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode,
1519 uint8_t u8DeliveryMode, uint8_t uVector, uint8_t u8Polarity,
1520 uint8_t u8TriggerMode, uint32_t uTagSrc)
1521{
1522 PDMDEV_ASSERT_DEVINS(pDevIns);
1523 PGVM pGVM = pDevIns->Internal.s.pGVM;
1524 LogFlow(("pdmR0IoApicHlp_ApicBusDeliver: caller=%p/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 uVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8 uTagSrc=%#x\n",
1525 pDevIns, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, uVector, u8Polarity, u8TriggerMode, uTagSrc));
1526 return APICBusDeliver(pGVM, u8Dest, u8DestMode, u8DeliveryMode, uVector, u8Polarity, u8TriggerMode, uTagSrc);
1527}
1528
1529
1530/** @interface_method_impl{PDMIOAPICHLP,pfnLock} */
1531static DECLCALLBACK(int) pdmR0IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
1532{
1533 PDMDEV_ASSERT_DEVINS(pDevIns);
1534 return pdmLockEx(pDevIns->Internal.s.pGVM, rc);
1535}
1536
1537
1538/** @interface_method_impl{PDMIOAPICHLP,pfnUnlock} */
1539static DECLCALLBACK(void) pdmR0IoApicHlp_Unlock(PPDMDEVINS pDevIns)
1540{
1541 PDMDEV_ASSERT_DEVINS(pDevIns);
1542 pdmUnlock(pDevIns->Internal.s.pGVM);
1543}
1544
1545
1546/** @interface_method_impl{PDMIOAPICHLP,pfnIommuMsiRemap} */
1547static DECLCALLBACK(int) pdmR0IoApicHlp_IommuMsiRemap(PPDMDEVINS pDevIns, uint16_t uDevId, PCMSIMSG pMsiIn, PMSIMSG pMsiOut)
1548{
1549 PDMDEV_ASSERT_DEVINS(pDevIns);
1550 LogFlow(("pdmR0IoApicHlp_IommuMsiRemap: caller='%s'/%d: pMsiIn=(%#RX64, %#RU32)\n", pDevIns->pReg->szName,
1551 pDevIns->iInstance, pMsiIn->Addr.u64, pMsiIn->Data.u32));
1552
1553#ifdef VBOX_WITH_IOMMU_AMD
1554 /** @todo IOMMU: Optimize/re-organize things here later. */
1555 PGVM pGVM = pDevIns->Internal.s.pGVM;
1556 PPDMIOMMUR0 pIommu = &pGVM->pdmr0.s.aIommus[0];
1557 PPDMDEVINS pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
1558 if ( pDevInsIommu
1559 && pDevInsIommu != pDevIns)
1560 {
1561 int rc = pIommu->pfnMsiRemap(pDevInsIommu, uDevId, pMsiIn, pMsiOut);
1562 if (RT_FAILURE(rc))
1563 {
1564 Log(("pdmR0IoApicHlp_IommuMsiRemap: IOMMU MSI remap failed. uDevId=%#x pMsiIn=(%#RX64, %#RU32) rc=%Rrc\n",
1565 uDevId, pMsiIn->Addr.u64, pMsiIn->Data.u32, rc));
1566 return rc;
1567 }
1568 }
1569#else
1570 RT_NOREF(pDevIns, uDevId);
1571 *pMsiOut = *pMsiIn;
1572#endif
1573 return VINF_SUCCESS;
1574}
1575
1576
1577/**
1578 * The Ring-0 I/O APIC Helper Callbacks.
1579 */
1580extern DECLEXPORT(const PDMIOAPICHLP) g_pdmR0IoApicHlp =
1581{
1582 PDM_IOAPICHLP_VERSION,
1583 pdmR0IoApicHlp_ApicBusDeliver,
1584 pdmR0IoApicHlp_Lock,
1585 pdmR0IoApicHlp_Unlock,
1586 pdmR0IoApicHlp_IommuMsiRemap,
1587 PDM_IOAPICHLP_VERSION
1588};
1589
1590/** @} */
1591
1592
1593
1594
1595/** @name PCI Bus Ring-0 Helpers
1596 * @{
1597 */
1598
1599/** @interface_method_impl{PDMPCIHLPR0,pfnIsaSetIrq} */
1600static DECLCALLBACK(void) pdmR0PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
1601{
1602 PDMDEV_ASSERT_DEVINS(pDevIns);
1603 Log4(("pdmR0PciHlp_IsaSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
1604 PGVM pGVM = pDevIns->Internal.s.pGVM;
1605
1606 pdmLock(pGVM);
1607 pdmR0IsaSetIrq(pGVM, iIrq, iLevel, uTagSrc);
1608 pdmUnlock(pGVM);
1609}
1610
1611
1612/** @interface_method_impl{PDMPCIHLPR0,pfnIoApicSetIrq} */
1613static DECLCALLBACK(void) pdmR0PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
1614{
1615 PDMDEV_ASSERT_DEVINS(pDevIns);
1616 Log4(("pdmR0PciHlp_IoApicSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
1617 PGVM pGVM = pDevIns->Internal.s.pGVM;
1618
1619 if (pGVM->pdm.s.IoApic.pDevInsR0)
1620 pGVM->pdm.s.IoApic.pfnSetIrqR0(pGVM->pdm.s.IoApic.pDevInsR0, iIrq, iLevel, uTagSrc);
1621 else if (pGVM->pdm.s.IoApic.pDevInsR3)
1622 {
1623 /* queue for ring-3 execution. */
1624 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM->pdm.s.pDevHlpQueueR0);
1625 if (pTask)
1626 {
1627 pTask->enmOp = PDMDEVHLPTASKOP_IOAPIC_SET_IRQ;
1628 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
1629 pTask->u.IoApicSetIRQ.iIrq = iIrq;
1630 pTask->u.IoApicSetIRQ.iLevel = iLevel;
1631 pTask->u.IoApicSetIRQ.uTagSrc = uTagSrc;
1632
1633 PDMQueueInsertEx(pGVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
1634 }
1635 else
1636 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
1637 }
1638}
1639
1640
1641/** @interface_method_impl{PDMPCIHLPR0,pfnIoApicSendMsi} */
1642static DECLCALLBACK(void) pdmR0PciHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc)
1643{
1644 PDMDEV_ASSERT_DEVINS(pDevIns);
1645 Log4(("pdmR0PciHlp_IoApicSendMsi: GCPhys=%p uValue=%d uTagSrc=%#x\n", GCPhys, uValue, uTagSrc));
1646 PGVM pGVM = pDevIns->Internal.s.pGVM;
1647 if (pGVM->pdm.s.IoApic.pDevInsR0)
1648 pGVM->pdm.s.IoApic.pfnSendMsiR0(pGVM->pdm.s.IoApic.pDevInsR0, GCPhys, uValue, uTagSrc);
1649 else
1650 AssertFatalMsgFailed(("Lazy bastards!"));
1651}
1652
1653
1654/** @interface_method_impl{PDMPCIHLPR0,pfnLock} */
1655static DECLCALLBACK(int) pdmR0PciHlp_Lock(PPDMDEVINS pDevIns, int rc)
1656{
1657 PDMDEV_ASSERT_DEVINS(pDevIns);
1658 return pdmLockEx(pDevIns->Internal.s.pGVM, rc);
1659}
1660
1661
1662/** @interface_method_impl{PDMPCIHLPR0,pfnUnlock} */
1663static DECLCALLBACK(void) pdmR0PciHlp_Unlock(PPDMDEVINS pDevIns)
1664{
1665 PDMDEV_ASSERT_DEVINS(pDevIns);
1666 pdmUnlock(pDevIns->Internal.s.pGVM);
1667}
1668
1669
1670/** @interface_method_impl{PDMPCIHLPR0,pfnGetBusByNo} */
1671static DECLCALLBACK(PPDMDEVINS) pdmR0PciHlp_GetBusByNo(PPDMDEVINS pDevIns, uint32_t idxPdmBus)
1672{
1673 PDMDEV_ASSERT_DEVINS(pDevIns);
1674 PGVM pGVM = pDevIns->Internal.s.pGVM;
1675 AssertReturn(idxPdmBus < RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses), NULL);
1676 PPDMDEVINS pRetDevIns = pGVM->pdmr0.s.aPciBuses[idxPdmBus].pDevInsR0;
1677 LogFlow(("pdmR3PciHlp_GetBusByNo: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pRetDevIns));
1678 return pRetDevIns;
1679}
1680
1681
1682/**
1683 * The Ring-0 PCI Bus Helper Callbacks.
1684 */
1685extern DECLEXPORT(const PDMPCIHLPR0) g_pdmR0PciHlp =
1686{
1687 PDM_PCIHLPR0_VERSION,
1688 pdmR0PciHlp_IsaSetIrq,
1689 pdmR0PciHlp_IoApicSetIrq,
1690 pdmR0PciHlp_IoApicSendMsi,
1691 pdmR0PciHlp_Lock,
1692 pdmR0PciHlp_Unlock,
1693 pdmR0PciHlp_GetBusByNo,
1694 PDM_PCIHLPR0_VERSION, /* the end */
1695};
1696
1697/** @} */
1698
1699
1700/** @name IOMMU Ring-0 Helpers
1701 * @{
1702 */
1703
1704/**
1705 * The Ring-0 IOMMU Helper Callbacks.
1706 */
1707extern DECLEXPORT(const PDMIOMMUHLPR0) g_pdmR0IommuHlp =
1708{
1709 PDM_IOMMUHLPR0_VERSION,
1710 PDM_IOMMUHLPR0_VERSION, /* the end */
1711};
1712
1713/** @} */
1714
1715
1716/** @name HPET Ring-0 Helpers
1717 * @{
1718 */
1719/* none */
1720
1721/**
1722 * The Ring-0 HPET Helper Callbacks.
1723 */
1724extern DECLEXPORT(const PDMHPETHLPR0) g_pdmR0HpetHlp =
1725{
1726 PDM_HPETHLPR0_VERSION,
1727 PDM_HPETHLPR0_VERSION, /* the end */
1728};
1729
1730/** @} */
1731
1732
1733/** @name Raw PCI Ring-0 Helpers
1734 * @{
1735 */
1736/* none */
1737
1738/**
1739 * The Ring-0 PCI raw Helper Callbacks.
1740 */
1741extern DECLEXPORT(const PDMPCIRAWHLPR0) g_pdmR0PciRawHlp =
1742{
1743 PDM_PCIRAWHLPR0_VERSION,
1744 PDM_PCIRAWHLPR0_VERSION, /* the end */
1745};
1746
1747/** @} */
1748
1749
1750
1751
1752/**
1753 * Sets an irq on the PIC and I/O APIC.
1754 *
1755 * @returns true if delivered, false if postponed.
1756 * @param pGVM The global (ring-0) VM structure.
1757 * @param iIrq The irq.
1758 * @param iLevel The new level.
1759 * @param uTagSrc The IRQ tag and source.
1760 *
1761 * @remarks The caller holds the PDM lock.
1762 */
1763DECLHIDDEN(bool) pdmR0IsaSetIrq(PGVM pGVM, int iIrq, int iLevel, uint32_t uTagSrc)
1764{
1765 if (RT_LIKELY( ( pGVM->pdm.s.IoApic.pDevInsR0
1766 || !pGVM->pdm.s.IoApic.pDevInsR3)
1767 && ( pGVM->pdm.s.Pic.pDevInsR0
1768 || !pGVM->pdm.s.Pic.pDevInsR3)))
1769 {
1770 if (pGVM->pdm.s.Pic.pDevInsR0)
1771 pGVM->pdm.s.Pic.pfnSetIrqR0(pGVM->pdm.s.Pic.pDevInsR0, iIrq, iLevel, uTagSrc);
1772 if (pGVM->pdm.s.IoApic.pDevInsR0)
1773 pGVM->pdm.s.IoApic.pfnSetIrqR0(pGVM->pdm.s.IoApic.pDevInsR0, iIrq, iLevel, uTagSrc);
1774 return true;
1775 }
1776
1777 /* queue for ring-3 execution. */
1778 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM->pdm.s.pDevHlpQueueR0);
1779 AssertReturn(pTask, false);
1780
1781 pTask->enmOp = PDMDEVHLPTASKOP_ISA_SET_IRQ;
1782 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
1783 pTask->u.IsaSetIRQ.iIrq = iIrq;
1784 pTask->u.IsaSetIRQ.iLevel = iLevel;
1785 pTask->u.IsaSetIRQ.uTagSrc = uTagSrc;
1786
1787 PDMQueueInsertEx(pGVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
1788 return false;
1789}
1790
Note: See TracBrowser for help on using the repository browser.

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