VirtualBox

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

Last change on this file since 104219 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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