VirtualBox

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

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

AMD IOMMU: bugref:9654 Fix accidentally not copying/initialize MSIMSG values. Fix using the translated memory address on
successful translations from the IOMMU. Fix not remapping any interrupt when IOMMU code is compiled but an IOMMU is not present.

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

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