VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/PDMR0Device.cpp@ 83941

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

AMD IOMMU: bugref:9654 Hook into PCIPhys[Read|Write] for intercepting and translating device accesses through the IOMMU.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 98.5 KB
Line 
1/* $Id: PDMR0Device.cpp 83941 2020-04-23 10:22:56Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, R0 Device 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/hm.h>
32#include <VBox/vmm/vmcc.h>
33#include <VBox/vmm/gvmm.h>
34
35#include <VBox/log.h>
36#include <VBox/err.h>
37#include <VBox/msi.h>
38#include <VBox/sup.h>
39#include <iprt/asm.h>
40#include <iprt/assert.h>
41#include <iprt/ctype.h>
42#include <iprt/mem.h>
43#include <iprt/memobj.h>
44#include <iprt/process.h>
45#include <iprt/string.h>
46
47#include "dtrace/VBoxVMM.h"
48#include "PDMInline.h"
49
50
51/*********************************************************************************************************************************
52* Global Variables *
53*********************************************************************************************************************************/
54RT_C_DECLS_BEGIN
55extern DECLEXPORT(const PDMDEVHLPR0) g_pdmR0DevHlp;
56extern DECLEXPORT(const PDMPICHLP) g_pdmR0PicHlp;
57extern DECLEXPORT(const PDMIOAPICHLP) g_pdmR0IoApicHlp;
58extern DECLEXPORT(const PDMPCIHLPR0) g_pdmR0PciHlp;
59extern DECLEXPORT(const PDMIOMMUHLPR0) g_pdmR0IommuHlp;
60extern DECLEXPORT(const PDMHPETHLPR0) g_pdmR0HpetHlp;
61extern DECLEXPORT(const PDMPCIRAWHLPR0) g_pdmR0PciRawHlp;
62extern DECLEXPORT(const PDMDRVHLPR0) g_pdmR0DrvHlp;
63RT_C_DECLS_END
64
65/** List of PDMDEVMODREGR0 structures protected by the loader lock. */
66static RTLISTANCHOR g_PDMDevModList;
67
68
69/**
70 * Pointer to the ring-0 device registrations for VMMR0.
71 */
72static const PDMDEVREGR0 *g_apVMM0DevRegs[] =
73{
74 &g_DeviceAPIC,
75};
76
77/**
78 * Module device registration record for VMMR0.
79 */
80static PDMDEVMODREGR0 g_VBoxDDR0ModDevReg =
81{
82 /* .u32Version = */ PDM_DEVMODREGR0_VERSION,
83 /* .cDevRegs = */ RT_ELEMENTS(g_apVMM0DevRegs),
84 /* .papDevRegs = */ &g_apVMM0DevRegs[0],
85 /* .hMod = */ NULL,
86 /* .ListEntry = */ { NULL, NULL },
87};
88
89
90/*********************************************************************************************************************************
91* Internal Functions *
92*********************************************************************************************************************************/
93static bool pdmR0IsaSetIrq(PGVM pGVM, int iIrq, int iLevel, uint32_t uTagSrc);
94
95
96/**
97 * Initializes the global ring-0 PDM data.
98 */
99VMMR0_INT_DECL(void) PDMR0Init(void *hMod)
100{
101 RTListInit(&g_PDMDevModList);
102 g_VBoxDDR0ModDevReg.hMod = hMod;
103 RTListAppend(&g_PDMDevModList, &g_VBoxDDR0ModDevReg.ListEntry);
104}
105
106
107/**
108 * Used by PDMR0CleanupVM to destroy a device instance.
109 *
110 * This is done during VM cleanup so that we're sure there are no active threads
111 * inside the device code.
112 *
113 * @param pGVM The global (ring-0) VM structure.
114 * @param pDevIns The device instance.
115 * @param idxR0Device The device instance handle.
116 */
117static int pdmR0DeviceDestroy(PGVM pGVM, PPDMDEVINSR0 pDevIns, uint32_t idxR0Device)
118{
119 /*
120 * Assert sanity.
121 */
122 Assert(idxR0Device < pGVM->pdmr0.s.cDevInstances);
123 AssertPtrReturn(pDevIns, VERR_INVALID_HANDLE);
124 Assert(pDevIns->u32Version == PDM_DEVINSR0_VERSION);
125 Assert(pDevIns->Internal.s.idxR0Device == idxR0Device);
126
127 /*
128 * Call the final destructor if there is one.
129 */
130 if (pDevIns->pReg->pfnFinalDestruct)
131 pDevIns->pReg->pfnFinalDestruct(pDevIns);
132 pDevIns->u32Version = ~PDM_DEVINSR0_VERSION;
133
134 /*
135 * Remove the device from the instance table.
136 */
137 Assert(pGVM->pdmr0.s.apDevInstances[idxR0Device] == pDevIns);
138 pGVM->pdmr0.s.apDevInstances[idxR0Device] = NULL;
139 if (idxR0Device + 1 == pGVM->pdmr0.s.cDevInstances)
140 pGVM->pdmr0.s.cDevInstances = idxR0Device;
141
142 /*
143 * Free the ring-3 mapping and instance memory.
144 */
145 RTR0MEMOBJ hMemObj = pDevIns->Internal.s.hMapObj;
146 pDevIns->Internal.s.hMapObj = NIL_RTR0MEMOBJ;
147 RTR0MemObjFree(hMemObj, true);
148
149 hMemObj = pDevIns->Internal.s.hMemObj;
150 pDevIns->Internal.s.hMemObj = NIL_RTR0MEMOBJ;
151 RTR0MemObjFree(hMemObj, true);
152
153 return VINF_SUCCESS;
154}
155
156
157/**
158 * Initializes the per-VM data for the PDM.
159 *
160 * This is called from under the GVMM lock, so it only need to initialize the
161 * data so PDMR0CleanupVM and others will work smoothly.
162 *
163 * @param pGVM Pointer to the global VM structure.
164 */
165VMMR0_INT_DECL(void) PDMR0InitPerVMData(PGVM pGVM)
166{
167 AssertCompile(sizeof(pGVM->pdm.s) <= sizeof(pGVM->pdm.padding));
168 AssertCompile(sizeof(pGVM->pdmr0.s) <= sizeof(pGVM->pdmr0.padding));
169
170 pGVM->pdmr0.s.cDevInstances = 0;
171}
172
173
174/**
175 * Cleans up any loose ends before the GVM structure is destroyed.
176 */
177VMMR0_INT_DECL(void) PDMR0CleanupVM(PGVM pGVM)
178{
179 uint32_t i = pGVM->pdmr0.s.cDevInstances;
180 while (i-- > 0)
181 {
182 PPDMDEVINSR0 pDevIns = pGVM->pdmr0.s.apDevInstances[i];
183 if (pDevIns)
184 pdmR0DeviceDestroy(pGVM, pDevIns, i);
185 }
186}
187
188
189/** @name Ring-0 Device Helpers
190 * @{
191 */
192
193/** @interface_method_impl{PDMDEVHLPR0,pfnIoPortSetUpContextEx} */
194static DECLCALLBACK(int) pdmR0DevHlp_IoPortSetUpContextEx(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts,
195 PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
196 PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr,
197 void *pvUser)
198{
199 PDMDEV_ASSERT_DEVINS(pDevIns);
200 LogFlow(("pdmR0DevHlp_IoPortSetUpContextEx: caller='%s'/%d: hIoPorts=%#x pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pvUser=%p\n",
201 pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser));
202 PGVM pGVM = pDevIns->Internal.s.pGVM;
203 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
204 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
205
206 int rc = IOMR0IoPortSetUpContext(pGVM, pDevIns, hIoPorts, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser);
207
208 LogFlow(("pdmR0DevHlp_IoPortSetUpContextEx: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
209 return rc;
210}
211
212
213/** @interface_method_impl{PDMDEVHLPR0,pfnMmioSetUpContextEx} */
214static DECLCALLBACK(int) pdmR0DevHlp_MmioSetUpContextEx(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, PFNIOMMMIONEWWRITE pfnWrite,
215 PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill, void *pvUser)
216{
217 PDMDEV_ASSERT_DEVINS(pDevIns);
218 LogFlow(("pdmR0DevHlp_MmioSetUpContextEx: caller='%s'/%d: hRegion=%#x pfnWrite=%p pfnRead=%p pfnFill=%p pvUser=%p\n",
219 pDevIns->pReg->szName, pDevIns->iInstance, hRegion, pfnWrite, pfnRead, pfnFill, pvUser));
220 PGVM pGVM = pDevIns->Internal.s.pGVM;
221 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
222 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
223
224 int rc = IOMR0MmioSetUpContext(pGVM, pDevIns, hRegion, pfnWrite, pfnRead, pfnFill, pvUser);
225
226 LogFlow(("pdmR0DevHlp_MmioSetUpContextEx: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
227 return rc;
228}
229
230
231/** @interface_method_impl{PDMDEVHLPR0,pfnMmio2SetUpContext} */
232static DECLCALLBACK(int) pdmR0DevHlp_Mmio2SetUpContext(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion,
233 size_t offSub, size_t cbSub, void **ppvMapping)
234{
235 PDMDEV_ASSERT_DEVINS(pDevIns);
236 LogFlow(("pdmR0DevHlp_Mmio2SetUpContext: caller='%s'/%d: hRegion=%#x offSub=%#zx cbSub=%#zx ppvMapping=%p\n",
237 pDevIns->pReg->szName, pDevIns->iInstance, hRegion, offSub, cbSub, ppvMapping));
238 *ppvMapping = NULL;
239
240 PGVM pGVM = pDevIns->Internal.s.pGVM;
241 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
242 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
243
244 int rc = PGMR0PhysMMIO2MapKernel(pGVM, pDevIns, hRegion, offSub, cbSub, ppvMapping);
245
246 LogFlow(("pdmR0DevHlp_Mmio2SetUpContext: caller='%s'/%d: returns %Rrc (%p)\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *ppvMapping));
247 return rc;
248}
249
250
251/** @interface_method_impl{PDMDEVHLPR0,pfnPCIPhysRead} */
252static DECLCALLBACK(int) pdmR0DevHlp_PCIPhysRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
253 void *pvBuf, size_t cbRead)
254{
255 PDMDEV_ASSERT_DEVINS(pDevIns);
256 if (!pPciDev) /* NULL is an alias for the default PCI device. */
257 pPciDev = pDevIns->apPciDevs[0];
258 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
259 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
260
261#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
262 /*
263 * Just check the busmaster setting here and forward the request to the generic read helper.
264 */
265 if (PCIDevIsBusmaster(pPciDev))
266 { /* likely */ }
267 else
268 {
269 Log(("pdmRCDevHlp_PCIPhysRead: caller=%p/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbRead=%#zx\n",
270 pDevIns, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbRead));
271 memset(pvBuf, 0xff, cbRead);
272 return VERR_PDM_NOT_PCI_BUS_MASTER;
273 }
274#endif
275
276#ifdef VBOX_WITH_IOMMU_AMD
277 /** @todo IOMMU: Optimize/re-organize things here later. */
278 PGVM pGVM = pDevIns->Internal.s.pGVM;
279 PPDMIOMMUR0 pIommu = &pGVM->pdmr0.s.aIommus[0];
280 PPDMDEVINS pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
281 if ( pDevInsIommu
282 && pDevInsIommu != pDevIns)
283 {
284 RTGCPHYS GCPhysOut;
285 uint16_t const uDeviceId = VBOX_PCI_BUSDEVFN_MAKE(pPciDev->Int.s.idxPdmBus, pPciDev->uDevFn);
286 int rc = pIommu->pfnMemRead(pDevInsIommu, uDeviceId, GCPhys, cbRead, &GCPhysOut);
287 if (RT_FAILURE(rc))
288 {
289 Log(("pdmR0DevHlp_PCIPhysRead: IOMMU translation failed. uDeviceId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDeviceId,
290 GCPhys, cbRead, rc));
291 return rc;
292 }
293 }
294#endif
295
296 return pDevIns->pHlpR0->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead);
297}
298
299
300/** @interface_method_impl{PDMDEVHLPR0,pfnPCIPhysWrite} */
301static DECLCALLBACK(int) pdmR0DevHlp_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
302 const void *pvBuf, size_t cbWrite)
303{
304 PDMDEV_ASSERT_DEVINS(pDevIns);
305 if (!pPciDev) /* NULL is an alias for the default PCI device. */
306 pPciDev = pDevIns->apPciDevs[0];
307 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
308 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
309
310#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
311 /*
312 * Just check the busmaster setting here and forward the request to the generic read helper.
313 */
314 if (PCIDevIsBusmaster(pPciDev))
315 { /* likely */ }
316 else
317 {
318 Log(("pdmRCDevHlp_PCIPhysWrite: caller=%p/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n",
319 pDevIns, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
320 return VERR_PDM_NOT_PCI_BUS_MASTER;
321 }
322#endif
323
324#ifdef VBOX_WITH_IOMMU_AMD
325 /** @todo IOMMU: Optimize/re-organize things here later. */
326 PGVM pGVM = pDevIns->Internal.s.pGVM;
327 PPDMIOMMUR0 pIommu = &pGVM->pdmr0.s.aIommus[0];
328 PPDMDEVINS pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
329 if ( pDevInsIommu
330 && pDevInsIommu != pDevIns)
331 {
332 RTGCPHYS GCPhysOut;
333 uint16_t const uDeviceId = VBOX_PCI_BUSDEVFN_MAKE(pPciDev->Int.s.idxPdmBus, pPciDev->uDevFn);
334 int rc = pIommu->pfnMemWrite(pDevInsIommu, uDeviceId, GCPhys, cbWrite, &GCPhysOut);
335 if (RT_FAILURE(rc))
336 {
337 Log(("pdmR0DevHlp_PCIPhysWrite: IOMMU translation failed. uDeviceId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDeviceId,
338 GCPhys, cbWrite, rc));
339 return rc;
340 }
341 }
342#endif
343
344 return pDevIns->pHlpR0->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite);
345}
346
347
348/** @interface_method_impl{PDMDEVHLPR0,pfnPCISetIrq} */
349static DECLCALLBACK(void) pdmR0DevHlp_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
350{
351 PDMDEV_ASSERT_DEVINS(pDevIns);
352 if (!pPciDev) /* NULL is an alias for the default PCI device. */
353 pPciDev = pDevIns->apPciDevs[0];
354 AssertReturnVoid(pPciDev);
355 LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
356 pDevIns, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
357 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
358
359 PGVM pGVM = pDevIns->Internal.s.pGVM;
360 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
361 AssertReturnVoid(idxBus < RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses));
362 PPDMPCIBUSR0 pPciBusR0 = &pGVM->pdmr0.s.aPciBuses[idxBus];
363
364 pdmLock(pGVM);
365
366 uint32_t uTagSrc;
367 if (iLevel & PDM_IRQ_LEVEL_HIGH)
368 {
369 pDevIns->Internal.s.pIntR3R0->uLastIrqTag = uTagSrc = pdmCalcIrqTag(pGVM, pDevIns->Internal.s.pInsR3R0->idTracing);
370 if (iLevel == PDM_IRQ_LEVEL_HIGH)
371 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
372 else
373 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
374 }
375 else
376 uTagSrc = pDevIns->Internal.s.pIntR3R0->uLastIrqTag;
377
378 if (pPciBusR0->pDevInsR0)
379 {
380 pPciBusR0->pfnSetIrqR0(pPciBusR0->pDevInsR0, pPciDev, iIrq, iLevel, uTagSrc);
381
382 pdmUnlock(pGVM);
383
384 if (iLevel == PDM_IRQ_LEVEL_LOW)
385 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
386 }
387 else
388 {
389 pdmUnlock(pGVM);
390
391 /* queue for ring-3 execution. */
392 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM->pdm.s.pDevHlpQueueR0);
393 AssertReturnVoid(pTask);
394
395 pTask->enmOp = PDMDEVHLPTASKOP_PCI_SET_IRQ;
396 pTask->pDevInsR3 = PDMDEVINS_2_R3PTR(pDevIns);
397 pTask->u.PciSetIRQ.iIrq = iIrq;
398 pTask->u.PciSetIRQ.iLevel = iLevel;
399 pTask->u.PciSetIRQ.uTagSrc = uTagSrc;
400 pTask->u.PciSetIRQ.pPciDevR3 = MMHyperR0ToR3(pGVM, pPciDev);
401
402 PDMQueueInsertEx(pGVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
403 }
404
405 LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, uTagSrc));
406}
407
408
409/** @interface_method_impl{PDMDEVHLPR0,pfnISASetIrq} */
410static DECLCALLBACK(void) pdmR0DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
411{
412 PDMDEV_ASSERT_DEVINS(pDevIns);
413 LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
414 PGVM pGVM = pDevIns->Internal.s.pGVM;
415
416 pdmLock(pGVM);
417 uint32_t uTagSrc;
418 if (iLevel & PDM_IRQ_LEVEL_HIGH)
419 {
420 pDevIns->Internal.s.pIntR3R0->uLastIrqTag = uTagSrc = pdmCalcIrqTag(pGVM, pDevIns->Internal.s.pInsR3R0->idTracing);
421 if (iLevel == PDM_IRQ_LEVEL_HIGH)
422 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
423 else
424 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
425 }
426 else
427 uTagSrc = pDevIns->Internal.s.pIntR3R0->uLastIrqTag;
428
429 bool fRc = pdmR0IsaSetIrq(pGVM, iIrq, iLevel, uTagSrc);
430
431 if (iLevel == PDM_IRQ_LEVEL_LOW && fRc)
432 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
433 pdmUnlock(pGVM);
434 LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, uTagSrc));
435}
436
437
438/** @interface_method_impl{PDMDEVHLPR0,pfnIoApicSendMsi} */
439static DECLCALLBACK(void) pdmR0DevHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue)
440{
441 PDMDEV_ASSERT_DEVINS(pDevIns);
442 LogFlow(("pdmR0DevHlp_IoApicSendMsi: caller=%p/%d: GCPhys=%RGp uValue=%#x\n", pDevIns, pDevIns->iInstance, GCPhys, uValue));
443 PGVM pGVM = pDevIns->Internal.s.pGVM;
444
445 uint32_t uTagSrc;
446 pDevIns->Internal.s.pIntR3R0->uLastIrqTag = uTagSrc = pdmCalcIrqTag(pGVM, pDevIns->Internal.s.pInsR3R0->idTracing);
447 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pGVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
448
449 if (pGVM->pdm.s.IoApic.pDevInsR0)
450 pGVM->pdm.s.IoApic.pfnSendMsiR0(pGVM->pdm.s.IoApic.pDevInsR0, GCPhys, uValue, uTagSrc);
451 else
452 AssertFatalMsgFailed(("Lazy bastards!"));
453
454 LogFlow(("pdmR0DevHlp_IoApicSendMsi: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, uTagSrc));
455}
456
457
458/** @interface_method_impl{PDMDEVHLPR0,pfnPhysRead} */
459static DECLCALLBACK(int) pdmR0DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
460{
461 PDMDEV_ASSERT_DEVINS(pDevIns);
462 LogFlow(("pdmR0DevHlp_PhysRead: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
463 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
464
465 VBOXSTRICTRC rcStrict = PGMPhysRead(pDevIns->Internal.s.pGVM, GCPhys, pvBuf, cbRead, PGMACCESSORIGIN_DEVICE);
466 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
467
468 Log(("pdmR0DevHlp_PhysRead: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
469 return VBOXSTRICTRC_VAL(rcStrict);
470}
471
472
473/** @interface_method_impl{PDMDEVHLPR0,pfnPhysWrite} */
474static DECLCALLBACK(int) pdmR0DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
475{
476 PDMDEV_ASSERT_DEVINS(pDevIns);
477 LogFlow(("pdmR0DevHlp_PhysWrite: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
478 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
479
480 VBOXSTRICTRC rcStrict = PGMPhysWrite(pDevIns->Internal.s.pGVM, GCPhys, pvBuf, cbWrite, PGMACCESSORIGIN_DEVICE);
481 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
482
483 Log(("pdmR0DevHlp_PhysWrite: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
484 return VBOXSTRICTRC_VAL(rcStrict);
485}
486
487
488/** @interface_method_impl{PDMDEVHLPR0,pfnA20IsEnabled} */
489static DECLCALLBACK(bool) pdmR0DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
490{
491 PDMDEV_ASSERT_DEVINS(pDevIns);
492 LogFlow(("pdmR0DevHlp_A20IsEnabled: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
493
494 bool fEnabled = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pGVM));
495
496 Log(("pdmR0DevHlp_A20IsEnabled: caller=%p/%d: returns %RTbool\n", pDevIns, pDevIns->iInstance, fEnabled));
497 return fEnabled;
498}
499
500
501/** @interface_method_impl{PDMDEVHLPR0,pfnVMState} */
502static DECLCALLBACK(VMSTATE) pdmR0DevHlp_VMState(PPDMDEVINS pDevIns)
503{
504 PDMDEV_ASSERT_DEVINS(pDevIns);
505
506 VMSTATE enmVMState = pDevIns->Internal.s.pGVM->enmVMState;
507
508 LogFlow(("pdmR0DevHlp_VMState: caller=%p/%d: returns %d\n", pDevIns, pDevIns->iInstance, enmVMState));
509 return enmVMState;
510}
511
512
513/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetError} */
514static DECLCALLBACK(int) pdmR0DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
515{
516 PDMDEV_ASSERT_DEVINS(pDevIns);
517 va_list args;
518 va_start(args, pszFormat);
519 int rc2 = VMSetErrorV(pDevIns->Internal.s.pGVM, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
520 va_end(args);
521 return rc;
522}
523
524
525/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetErrorV} */
526static DECLCALLBACK(int) pdmR0DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
527{
528 PDMDEV_ASSERT_DEVINS(pDevIns);
529 int rc2 = VMSetErrorV(pDevIns->Internal.s.pGVM, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
530 return rc;
531}
532
533
534/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetRuntimeError} */
535static DECLCALLBACK(int) pdmR0DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
536{
537 PDMDEV_ASSERT_DEVINS(pDevIns);
538 va_list va;
539 va_start(va, pszFormat);
540 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pGVM, fFlags, pszErrorId, pszFormat, va);
541 va_end(va);
542 return rc;
543}
544
545
546/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetRuntimeErrorV} */
547static DECLCALLBACK(int) pdmR0DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
548{
549 PDMDEV_ASSERT_DEVINS(pDevIns);
550 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pGVM, fFlags, pszErrorId, pszFormat, va);
551 return rc;
552}
553
554
555
556/** @interface_method_impl{PDMDEVHLPR0,pfnGetVM} */
557static DECLCALLBACK(PVMCC) pdmR0DevHlp_GetVM(PPDMDEVINS pDevIns)
558{
559 PDMDEV_ASSERT_DEVINS(pDevIns);
560 LogFlow(("pdmR0DevHlp_GetVM: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
561 return pDevIns->Internal.s.pGVM;
562}
563
564
565/** @interface_method_impl{PDMDEVHLPR0,pfnGetVMCPU} */
566static DECLCALLBACK(PVMCPUCC) pdmR0DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
567{
568 PDMDEV_ASSERT_DEVINS(pDevIns);
569 LogFlow(("pdmR0DevHlp_GetVMCPU: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
570 return VMMGetCpu(pDevIns->Internal.s.pGVM);
571}
572
573
574/** @interface_method_impl{PDMDEVHLPRC,pfnGetCurrentCpuId} */
575static DECLCALLBACK(VMCPUID) pdmR0DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
576{
577 PDMDEV_ASSERT_DEVINS(pDevIns);
578 VMCPUID idCpu = VMMGetCpuId(pDevIns->Internal.s.pGVM);
579 LogFlow(("pdmR0DevHlp_GetCurrentCpuId: caller='%p'/%d for CPU %u\n", pDevIns, pDevIns->iInstance, idCpu));
580 return idCpu;
581}
582
583
584/** @interface_method_impl{PDMDEVHLPR0,pfnTimerToPtr} */
585static DECLCALLBACK(PTMTIMERR0) pdmR0DevHlp_TimerToPtr(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
586{
587 PDMDEV_ASSERT_DEVINS(pDevIns);
588 RT_NOREF(pDevIns);
589 return (PTMTIMERR0)MMHyperR3ToCC(pDevIns->Internal.s.pGVM, hTimer);
590}
591
592
593/** @interface_method_impl{PDMDEVHLPR0,pfnTimerFromMicro} */
594static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerFromMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicroSecs)
595{
596 return TMTimerFromMicro(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cMicroSecs);
597}
598
599
600/** @interface_method_impl{PDMDEVHLPR0,pfnTimerFromMilli} */
601static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerFromMilli(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliSecs)
602{
603 return TMTimerFromMilli(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cMilliSecs);
604}
605
606
607/** @interface_method_impl{PDMDEVHLPR0,pfnTimerFromNano} */
608static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerFromNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanoSecs)
609{
610 return TMTimerFromNano(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cNanoSecs);
611}
612
613/** @interface_method_impl{PDMDEVHLPR0,pfnTimerGet} */
614static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerGet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
615{
616 return TMTimerGet(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
617}
618
619
620/** @interface_method_impl{PDMDEVHLPR0,pfnTimerGetFreq} */
621static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerGetFreq(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
622{
623 return TMTimerGetFreq(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
624}
625
626
627/** @interface_method_impl{PDMDEVHLPR0,pfnTimerGetNano} */
628static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerGetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
629{
630 return TMTimerGetNano(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
631}
632
633
634/** @interface_method_impl{PDMDEVHLPR0,pfnTimerIsActive} */
635static DECLCALLBACK(bool) pdmR0DevHlp_TimerIsActive(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
636{
637 return TMTimerIsActive(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
638}
639
640
641/** @interface_method_impl{PDMDEVHLPR0,pfnTimerIsLockOwner} */
642static DECLCALLBACK(bool) pdmR0DevHlp_TimerIsLockOwner(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
643{
644 return TMTimerIsLockOwner(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
645}
646
647
648/** @interface_method_impl{PDMDEVHLPR0,pfnTimerLockClock} */
649static DECLCALLBACK(VBOXSTRICTRC) pdmR0DevHlp_TimerLockClock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, int rcBusy)
650{
651 return TMTimerLock(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), rcBusy);
652}
653
654
655/** @interface_method_impl{PDMDEVHLPR0,pfnTimerLockClock2} */
656static DECLCALLBACK(VBOXSTRICTRC) pdmR0DevHlp_TimerLockClock2(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer,
657 PPDMCRITSECT pCritSect, int rcBusy)
658{
659 VBOXSTRICTRC rc = TMTimerLock(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), rcBusy);
660 if (rc == VINF_SUCCESS)
661 {
662 rc = PDMCritSectEnter(pCritSect, rcBusy);
663 if (rc == VINF_SUCCESS)
664 return rc;
665 AssertRC(VBOXSTRICTRC_VAL(rc));
666 TMTimerUnlock(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
667 }
668 else
669 AssertRC(VBOXSTRICTRC_VAL(rc));
670 return rc;
671}
672
673
674/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSet} */
675static DECLCALLBACK(int) pdmR0DevHlp_TimerSet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t uExpire)
676{
677 return TMTimerSet(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), uExpire);
678}
679
680
681/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetFrequencyHint} */
682static DECLCALLBACK(int) pdmR0DevHlp_TimerSetFrequencyHint(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint32_t uHz)
683{
684 return TMTimerSetFrequencyHint(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), uHz);
685}
686
687
688/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetMicro} */
689static DECLCALLBACK(int) pdmR0DevHlp_TimerSetMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext)
690{
691 return TMTimerSetMicro(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cMicrosToNext);
692}
693
694
695/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetMillies} */
696static DECLCALLBACK(int) pdmR0DevHlp_TimerSetMillies(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext)
697{
698 return TMTimerSetMillies(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cMilliesToNext);
699}
700
701
702/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetNano} */
703static DECLCALLBACK(int) pdmR0DevHlp_TimerSetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanosToNext)
704{
705 return TMTimerSetNano(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cNanosToNext);
706}
707
708
709/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetRelative} */
710static DECLCALLBACK(int) pdmR0DevHlp_TimerSetRelative(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now)
711{
712 return TMTimerSetRelative(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer), cTicksToNext, pu64Now);
713}
714
715
716/** @interface_method_impl{PDMDEVHLPR0,pfnTimerStop} */
717static DECLCALLBACK(int) pdmR0DevHlp_TimerStop(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
718{
719 return TMTimerStop(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
720}
721
722
723/** @interface_method_impl{PDMDEVHLPR0,pfnTimerUnlockClock} */
724static DECLCALLBACK(void) pdmR0DevHlp_TimerUnlockClock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
725{
726 TMTimerUnlock(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
727}
728
729
730/** @interface_method_impl{PDMDEVHLPR0,pfnTimerUnlockClock2} */
731static DECLCALLBACK(void) pdmR0DevHlp_TimerUnlockClock2(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect)
732{
733 TMTimerUnlock(pdmR0DevHlp_TimerToPtr(pDevIns, hTimer));
734 int rc = PDMCritSectLeave(pCritSect);
735 AssertRC(rc);
736}
737
738
739/** @interface_method_impl{PDMDEVHLPR0,pfnTMTimeVirtGet} */
740static DECLCALLBACK(uint64_t) pdmR0DevHlp_TMTimeVirtGet(PPDMDEVINS pDevIns)
741{
742 PDMDEV_ASSERT_DEVINS(pDevIns);
743 LogFlow(("pdmR0DevHlp_TMTimeVirtGet: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
744 return TMVirtualGet(pDevIns->Internal.s.pGVM);
745}
746
747
748/** @interface_method_impl{PDMDEVHLPR0,pfnTMTimeVirtGetFreq} */
749static DECLCALLBACK(uint64_t) pdmR0DevHlp_TMTimeVirtGetFreq(PPDMDEVINS pDevIns)
750{
751 PDMDEV_ASSERT_DEVINS(pDevIns);
752 LogFlow(("pdmR0DevHlp_TMTimeVirtGetFreq: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
753 return TMVirtualGetFreq(pDevIns->Internal.s.pGVM);
754}
755
756
757/** @interface_method_impl{PDMDEVHLPR0,pfnTMTimeVirtGetNano} */
758static DECLCALLBACK(uint64_t) pdmR0DevHlp_TMTimeVirtGetNano(PPDMDEVINS pDevIns)
759{
760 PDMDEV_ASSERT_DEVINS(pDevIns);
761 LogFlow(("pdmR0DevHlp_TMTimeVirtGetNano: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
762 return TMVirtualToNano(pDevIns->Internal.s.pGVM, TMVirtualGet(pDevIns->Internal.s.pGVM));
763}
764
765
766/** @interface_method_impl{PDMDEVHLPR0,pfnQueueToPtr} */
767static DECLCALLBACK(PPDMQUEUE) pdmR0DevHlp_QueueToPtr(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
768{
769 PDMDEV_ASSERT_DEVINS(pDevIns);
770 RT_NOREF(pDevIns);
771 return (PPDMQUEUE)MMHyperR3ToCC(pDevIns->Internal.s.pGVM, hQueue);
772}
773
774
775/** @interface_method_impl{PDMDEVHLPR0,pfnQueueAlloc} */
776static DECLCALLBACK(PPDMQUEUEITEMCORE) pdmR0DevHlp_QueueAlloc(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
777{
778 return PDMQueueAlloc(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue));
779}
780
781
782/** @interface_method_impl{PDMDEVHLPR0,pfnQueueInsert} */
783static DECLCALLBACK(void) pdmR0DevHlp_QueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)
784{
785 return PDMQueueInsert(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue), pItem);
786}
787
788
789/** @interface_method_impl{PDMDEVHLPR0,pfnQueueInsertEx} */
790static DECLCALLBACK(void) pdmR0DevHlp_QueueInsertEx(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem,
791 uint64_t cNanoMaxDelay)
792{
793 return PDMQueueInsertEx(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue), pItem, cNanoMaxDelay);
794}
795
796
797/** @interface_method_impl{PDMDEVHLPR0,pfnQueueFlushIfNecessary} */
798static DECLCALLBACK(bool) pdmR0DevHlp_QueueFlushIfNecessary(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
799{
800 return PDMQueueFlushIfNecessary(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue));
801}
802
803
804/** @interface_method_impl{PDMDEVHLPR0,pfnTaskTrigger} */
805static DECLCALLBACK(int) pdmR0DevHlp_TaskTrigger(PPDMDEVINS pDevIns, PDMTASKHANDLE hTask)
806{
807 PDMDEV_ASSERT_DEVINS(pDevIns);
808 LogFlow(("pdmR0DevHlp_TaskTrigger: caller='%s'/%d: hTask=%RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, hTask));
809
810 int rc = PDMTaskTrigger(pDevIns->Internal.s.pGVM, PDMTASKTYPE_DEV, pDevIns->pDevInsForR3, hTask);
811
812 LogFlow(("pdmR0DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
813 return rc;
814}
815
816
817/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventSignal} */
818static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventSignal(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
819{
820 PDMDEV_ASSERT_DEVINS(pDevIns);
821 LogFlow(("pdmR0DevHlp_SUPSemEventSignal: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
822
823 int rc = SUPSemEventSignal(pDevIns->Internal.s.pGVM->pSession, hEvent);
824
825 LogFlow(("pdmR0DevHlp_SUPSemEventSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
826 return rc;
827}
828
829
830/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventWaitNoResume} */
831static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint32_t cMillies)
832{
833 PDMDEV_ASSERT_DEVINS(pDevIns);
834 LogFlow(("pdmR0DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: hEvent=%p cNsTimeout=%RU32\n",
835 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cMillies));
836
837 int rc = SUPSemEventWaitNoResume(pDevIns->Internal.s.pGVM->pSession, hEvent, cMillies);
838
839 LogFlow(("pdmR0DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
840 return rc;
841}
842
843
844/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventWaitNsAbsIntr} */
845static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
846{
847 PDMDEV_ASSERT_DEVINS(pDevIns);
848 LogFlow(("pdmR0DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: hEvent=%p uNsTimeout=%RU64\n",
849 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, uNsTimeout));
850
851 int rc = SUPSemEventWaitNsAbsIntr(pDevIns->Internal.s.pGVM->pSession, hEvent, uNsTimeout);
852
853 LogFlow(("pdmR0DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
854 return rc;
855}
856
857
858/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventWaitNsRelIntr} */
859static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
860{
861 PDMDEV_ASSERT_DEVINS(pDevIns);
862 LogFlow(("pdmR0DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: hEvent=%p cNsTimeout=%RU64\n",
863 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cNsTimeout));
864
865 int rc = SUPSemEventWaitNsRelIntr(pDevIns->Internal.s.pGVM->pSession, hEvent, cNsTimeout);
866
867 LogFlow(("pdmR0DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
868 return rc;
869}
870
871
872/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventGetResolution} */
873static DECLCALLBACK(uint32_t) pdmR0DevHlp_SUPSemEventGetResolution(PPDMDEVINS pDevIns)
874{
875 PDMDEV_ASSERT_DEVINS(pDevIns);
876 LogFlow(("pdmR0DevHlp_SUPSemEventGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
877
878 uint32_t cNsResolution = SUPSemEventGetResolution(pDevIns->Internal.s.pGVM->pSession);
879
880 LogFlow(("pdmR0DevHlp_SUPSemEventGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
881 return cNsResolution;
882}
883
884
885/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiSignal} */
886static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiSignal(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
887{
888 PDMDEV_ASSERT_DEVINS(pDevIns);
889 LogFlow(("pdmR0DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
890
891 int rc = SUPSemEventMultiSignal(pDevIns->Internal.s.pGVM->pSession, hEventMulti);
892
893 LogFlow(("pdmR0DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
894 return rc;
895}
896
897
898/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiReset} */
899static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiReset(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
900{
901 PDMDEV_ASSERT_DEVINS(pDevIns);
902 LogFlow(("pdmR0DevHlp_SUPSemEventMultiReset: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
903
904 int rc = SUPSemEventMultiReset(pDevIns->Internal.s.pGVM->pSession, hEventMulti);
905
906 LogFlow(("pdmR0DevHlp_SUPSemEventMultiReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
907 return rc;
908}
909
910
911/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiWaitNoResume} */
912static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
913 uint32_t cMillies)
914{
915 PDMDEV_ASSERT_DEVINS(pDevIns);
916 LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: hEventMulti=%p cMillies=%RU32\n",
917 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cMillies));
918
919 int rc = SUPSemEventMultiWaitNoResume(pDevIns->Internal.s.pGVM->pSession, hEventMulti, cMillies);
920
921 LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
922 return rc;
923}
924
925
926/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiWaitNsAbsIntr} */
927static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
928 uint64_t uNsTimeout)
929{
930 PDMDEV_ASSERT_DEVINS(pDevIns);
931 LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: hEventMulti=%p uNsTimeout=%RU64\n",
932 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, uNsTimeout));
933
934 int rc = SUPSemEventMultiWaitNsAbsIntr(pDevIns->Internal.s.pGVM->pSession, hEventMulti, uNsTimeout);
935
936 LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
937 return rc;
938}
939
940
941/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiWaitNsRelIntr} */
942static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
943 uint64_t cNsTimeout)
944{
945 PDMDEV_ASSERT_DEVINS(pDevIns);
946 LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: hEventMulti=%p cNsTimeout=%RU64\n",
947 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cNsTimeout));
948
949 int rc = SUPSemEventMultiWaitNsRelIntr(pDevIns->Internal.s.pGVM->pSession, hEventMulti, cNsTimeout);
950
951 LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
952 return rc;
953}
954
955
956/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiGetResolution} */
957static DECLCALLBACK(uint32_t) pdmR0DevHlp_SUPSemEventMultiGetResolution(PPDMDEVINS pDevIns)
958{
959 PDMDEV_ASSERT_DEVINS(pDevIns);
960 LogFlow(("pdmR0DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
961
962 uint32_t cNsResolution = SUPSemEventMultiGetResolution(pDevIns->Internal.s.pGVM->pSession);
963
964 LogFlow(("pdmR0DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
965 return cNsResolution;
966}
967
968
969/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectGetNop} */
970static DECLCALLBACK(PPDMCRITSECT) pdmR0DevHlp_CritSectGetNop(PPDMDEVINS pDevIns)
971{
972 PDMDEV_ASSERT_DEVINS(pDevIns);
973 PGVM pGVM = pDevIns->Internal.s.pGVM;
974
975 PPDMCRITSECT pCritSect = &pGVM->pdm.s.NopCritSect;
976 LogFlow(("pdmR0DevHlp_CritSectGetNop: caller='%s'/%d: return %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
977 return pCritSect;
978}
979
980
981/** @interface_method_impl{PDMDEVHLPR0,pfnSetDeviceCritSect} */
982static DECLCALLBACK(int) pdmR0DevHlp_SetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
983{
984 /*
985 * Validate input.
986 *
987 * Note! We only allow the automatically created default critical section
988 * to be replaced by this API.
989 */
990 PDMDEV_ASSERT_DEVINS(pDevIns);
991 AssertPtrReturn(pCritSect, VERR_INVALID_POINTER);
992 LogFlow(("pdmR0DevHlp_SetDeviceCritSect: caller='%s'/%d: pCritSect=%p (%s)\n",
993 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pCritSect->s.pszName));
994 AssertReturn(PDMCritSectIsInitialized(pCritSect), VERR_INVALID_PARAMETER);
995 PGVM pGVM = pDevIns->Internal.s.pGVM;
996 AssertReturn(pCritSect->s.pVMR0 == pGVM, VERR_INVALID_PARAMETER);
997
998 VM_ASSERT_EMT(pGVM);
999 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1000
1001 /*
1002 * Check that ring-3 has already done this, then effect the change.
1003 */
1004 AssertReturn(pDevIns->pDevInsForR3R0->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_CHANGED_CRITSECT, VERR_WRONG_ORDER);
1005 pDevIns->pCritSectRoR0 = pCritSect;
1006
1007 LogFlow(("pdmR0DevHlp_SetDeviceCritSect: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
1008 return VINF_SUCCESS;
1009}
1010
1011
1012/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectEnter} */
1013static DECLCALLBACK(int) pdmR0DevHlp_CritSectEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy)
1014{
1015 PDMDEV_ASSERT_DEVINS(pDevIns);
1016 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pGVM to the crit sect code. */
1017 return PDMCritSectEnter(pCritSect, rcBusy);
1018}
1019
1020
1021/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectEnterDebug} */
1022static DECLCALLBACK(int) pdmR0DevHlp_CritSectEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
1023{
1024 PDMDEV_ASSERT_DEVINS(pDevIns);
1025 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pGVM to the crit sect code. */
1026 return PDMCritSectEnterDebug(pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
1027}
1028
1029
1030/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectTryEnter} */
1031static DECLCALLBACK(int) pdmR0DevHlp_CritSectTryEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
1032{
1033 PDMDEV_ASSERT_DEVINS(pDevIns);
1034 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pGVM to the crit sect code. */
1035 return PDMCritSectTryEnter(pCritSect);
1036}
1037
1038
1039/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectTryEnterDebug} */
1040static DECLCALLBACK(int) pdmR0DevHlp_CritSectTryEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
1041{
1042 PDMDEV_ASSERT_DEVINS(pDevIns);
1043 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pGVM to the crit sect code. */
1044 return PDMCritSectTryEnterDebug(pCritSect, uId, RT_SRC_POS_ARGS);
1045}
1046
1047
1048/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectLeave} */
1049static DECLCALLBACK(int) pdmR0DevHlp_CritSectLeave(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
1050{
1051 PDMDEV_ASSERT_DEVINS(pDevIns);
1052 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pGVM to the crit sect code. */
1053 return PDMCritSectLeave(pCritSect);
1054}
1055
1056
1057/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectIsOwner} */
1058static DECLCALLBACK(bool) pdmR0DevHlp_CritSectIsOwner(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
1059{
1060 PDMDEV_ASSERT_DEVINS(pDevIns);
1061 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pGVM to the crit sect code. */
1062 return PDMCritSectIsOwner(pCritSect);
1063}
1064
1065
1066/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectIsInitialized} */
1067static DECLCALLBACK(bool) pdmR0DevHlp_CritSectIsInitialized(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
1068{
1069 PDMDEV_ASSERT_DEVINS(pDevIns);
1070 RT_NOREF(pDevIns);
1071 return PDMCritSectIsInitialized(pCritSect);
1072}
1073
1074
1075/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectHasWaiters} */
1076static DECLCALLBACK(bool) pdmR0DevHlp_CritSectHasWaiters(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
1077{
1078 PDMDEV_ASSERT_DEVINS(pDevIns);
1079 RT_NOREF(pDevIns);
1080 return PDMCritSectHasWaiters(pCritSect);
1081}
1082
1083
1084/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectGetRecursion} */
1085static DECLCALLBACK(uint32_t) pdmR0DevHlp_CritSectGetRecursion(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
1086{
1087 PDMDEV_ASSERT_DEVINS(pDevIns);
1088 RT_NOREF(pDevIns);
1089 return PDMCritSectGetRecursion(pCritSect);
1090}
1091
1092
1093/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectScheduleExitEvent} */
1094static DECLCALLBACK(int) pdmR0DevHlp_CritSectScheduleExitEvent(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect,
1095 SUPSEMEVENT hEventToSignal)
1096{
1097 PDMDEV_ASSERT_DEVINS(pDevIns);
1098 RT_NOREF(pDevIns);
1099 return PDMHCCritSectScheduleExitEvent(pCritSect, hEventToSignal);
1100}
1101
1102
1103/** @interface_method_impl{PDMDEVHLPR0,pfnDBGFTraceBuf} */
1104static DECLCALLBACK(RTTRACEBUF) pdmR0DevHlp_DBGFTraceBuf(PPDMDEVINS pDevIns)
1105{
1106 PDMDEV_ASSERT_DEVINS(pDevIns);
1107 RTTRACEBUF hTraceBuf = pDevIns->Internal.s.pGVM->hTraceBufR0;
1108 LogFlow(("pdmR0DevHlp_DBGFTraceBuf: caller='%p'/%d: returns %p\n", pDevIns, pDevIns->iInstance, hTraceBuf));
1109 return hTraceBuf;
1110}
1111
1112
1113/** @interface_method_impl{PDMDEVHLPR0,pfnPCIBusSetUpContext} */
1114static DECLCALLBACK(int) pdmR0DevHlp_PCIBusSetUpContext(PPDMDEVINS pDevIns, PPDMPCIBUSREGR0 pPciBusReg, PCPDMPCIHLPR0 *ppPciHlp)
1115{
1116 PDMDEV_ASSERT_DEVINS(pDevIns);
1117 LogFlow(("pdmR0DevHlp_PCIBusSetUpContext: caller='%p'/%d: pPciBusReg=%p{.u32Version=%#x, .iBus=%#u, .pfnSetIrq=%p, u32EnvVersion=%#x} ppPciHlp=%p\n",
1118 pDevIns, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->iBus, pPciBusReg->pfnSetIrq,
1119 pPciBusReg->u32EndVersion, ppPciHlp));
1120 PGVM pGVM = pDevIns->Internal.s.pGVM;
1121
1122 /*
1123 * Validate input.
1124 */
1125 AssertPtrReturn(pPciBusReg, VERR_INVALID_POINTER);
1126 AssertLogRelMsgReturn(pPciBusReg->u32Version == PDM_PCIBUSREGCC_VERSION,
1127 ("%#x vs %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGCC_VERSION), VERR_VERSION_MISMATCH);
1128 AssertPtrReturn(pPciBusReg->pfnSetIrq, VERR_INVALID_POINTER);
1129 AssertLogRelMsgReturn(pPciBusReg->u32EndVersion == PDM_PCIBUSREGCC_VERSION,
1130 ("%#x vs %#x\n", pPciBusReg->u32EndVersion, PDM_PCIBUSREGCC_VERSION), VERR_VERSION_MISMATCH);
1131
1132 AssertPtrReturn(ppPciHlp, VERR_INVALID_POINTER);
1133
1134 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1135 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
1136
1137 /* Check the shared bus data (registered earlier from ring-3): */
1138 uint32_t iBus = pPciBusReg->iBus;
1139 ASMCompilerBarrier();
1140 AssertLogRelMsgReturn(iBus < RT_ELEMENTS(pGVM->pdm.s.aPciBuses), ("iBus=%#x\n", iBus), VERR_OUT_OF_RANGE);
1141 PPDMPCIBUS pPciBusShared = &pGVM->pdm.s.aPciBuses[iBus];
1142 AssertLogRelMsgReturn(pPciBusShared->iBus == iBus, ("%u vs %u\n", pPciBusShared->iBus, iBus), VERR_INVALID_PARAMETER);
1143 AssertLogRelMsgReturn(pPciBusShared->pDevInsR3 == pDevIns->pDevInsForR3,
1144 ("%p vs %p (iBus=%u)\n", pPciBusShared->pDevInsR3, pDevIns->pDevInsForR3, iBus), VERR_NOT_OWNER);
1145
1146 /* Check that the bus isn't already registered in ring-0: */
1147 AssertCompile(RT_ELEMENTS(pGVM->pdm.s.aPciBuses) == RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses));
1148 PPDMPCIBUSR0 pPciBusR0 = &pGVM->pdmr0.s.aPciBuses[iBus];
1149 AssertLogRelMsgReturn(pPciBusR0->pDevInsR0 == NULL,
1150 ("%p (caller pDevIns=%p, iBus=%u)\n", pPciBusR0->pDevInsR0, pDevIns, iBus),
1151 VERR_ALREADY_EXISTS);
1152
1153 /*
1154 * Do the registering.
1155 */
1156 pPciBusR0->iBus = iBus;
1157 pPciBusR0->uPadding0 = 0xbeefbeef;
1158 pPciBusR0->pfnSetIrqR0 = pPciBusReg->pfnSetIrq;
1159 pPciBusR0->pDevInsR0 = pDevIns;
1160
1161 *ppPciHlp = &g_pdmR0PciHlp;
1162
1163 LogFlow(("pdmR0DevHlp_PCIBusSetUpContext: caller='%p'/%d: returns VINF_SUCCESS\n", pDevIns, pDevIns->iInstance));
1164 return VINF_SUCCESS;
1165}
1166
1167
1168/** @interface_method_impl{PDMDEVHLPR0,pfnIommuSetUpContext} */
1169static DECLCALLBACK(int) pdmR0DevHlp_IommuSetUpContext(PPDMDEVINS pDevIns, PPDMIOMMUREGR0 pIommuReg, PCPDMIOMMUHLPR0 *ppIommuHlp)
1170{
1171 PDMDEV_ASSERT_DEVINS(pDevIns);
1172 LogFlow(("pdmR0DevHlp_IommuSetUpContext: caller='%p'/%d: pIommuReg=%p{.u32Version=%#x, u32TheEnd=%#x} ppIommuHlp=%p\n",
1173 pDevIns, pDevIns->iInstance, pIommuReg, pIommuReg->u32Version, pIommuReg->u32TheEnd, ppIommuHlp));
1174 PGVM pGVM = pDevIns->Internal.s.pGVM;
1175
1176 /*
1177 * Validate input.
1178 */
1179 AssertPtrReturn(pIommuReg, VERR_INVALID_POINTER);
1180 AssertLogRelMsgReturn(pIommuReg->u32Version == PDM_IOMMUREGCC_VERSION,
1181 ("%#x vs %#x\n", pIommuReg->u32Version, PDM_IOMMUREGCC_VERSION), VERR_VERSION_MISMATCH);
1182 AssertLogRelMsgReturn(pIommuReg->u32TheEnd == PDM_IOMMUREGCC_VERSION,
1183 ("%#x vs %#x\n", pIommuReg->u32TheEnd, PDM_IOMMUREGCC_VERSION), VERR_VERSION_MISMATCH);
1184
1185 AssertPtrReturn(ppIommuHlp, VERR_INVALID_POINTER);
1186
1187 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1188 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
1189
1190 /* Check the IOMMU shared data (registered earlier from ring-3). */
1191 uint32_t const idxIommu = pIommuReg->idxIommu;
1192 ASMCompilerBarrier();
1193 AssertLogRelMsgReturn(idxIommu < RT_ELEMENTS(pGVM->pdm.s.aIommus), ("idxIommu=%#x\n", idxIommu), VERR_OUT_OF_RANGE);
1194 PPDMIOMMU pIommuShared = &pGVM->pdm.s.aIommus[idxIommu];
1195 AssertLogRelMsgReturn(pIommuShared->idxIommu == idxIommu, ("%u vs %u\n", pIommuShared->idxIommu, idxIommu), VERR_INVALID_PARAMETER);
1196 AssertLogRelMsgReturn(pIommuShared->pDevInsR3 == pDevIns->pDevInsForR3,
1197 ("%p vs %p (idxIommu=%u)\n", pIommuShared->pDevInsR3, pDevIns->pDevInsForR3, idxIommu), VERR_NOT_OWNER);
1198
1199 /* Check that the IOMMU isn't already registered in ring-0. */
1200 AssertCompile(RT_ELEMENTS(pGVM->pdm.s.aIommus) == RT_ELEMENTS(pGVM->pdmr0.s.aIommus));
1201 PPDMIOMMUR0 pIommuR0 = &pGVM->pdmr0.s.aIommus[idxIommu];
1202 AssertLogRelMsgReturn(pIommuR0->pDevInsR0 == NULL,
1203 ("%p (caller pDevIns=%p, idxIommu=%u)\n", pIommuR0->pDevInsR0, pDevIns, idxIommu),
1204 VERR_ALREADY_EXISTS);
1205
1206 /*
1207 * Register.
1208 */
1209 pIommuR0->idxIommu = idxIommu;
1210 pIommuR0->uPadding0 = 0xdeaddead;
1211 pIommuR0->pDevInsR0 = pDevIns;
1212
1213 *ppIommuHlp = &g_pdmR0IommuHlp;
1214
1215 LogFlow(("pdmR0DevHlp_IommuSetUpContext: caller='%p'/%d: returns VINF_SUCCESS\n", pDevIns, pDevIns->iInstance));
1216 return VINF_SUCCESS;
1217}
1218
1219
1220/** @interface_method_impl{PDMDEVHLPR0,pfnPICSetUpContext} */
1221static DECLCALLBACK(int) pdmR0DevHlp_PICSetUpContext(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp)
1222{
1223 PDMDEV_ASSERT_DEVINS(pDevIns);
1224 LogFlow(("pdmR0DevHlp_PICSetUpContext: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnGetInterrupt=%p, .u32TheEnd=%#x } ppPicHlp=%p\n",
1225 pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrq, pPicReg->pfnGetInterrupt, pPicReg->u32TheEnd, ppPicHlp));
1226 PGVM pGVM = pDevIns->Internal.s.pGVM;
1227
1228 /*
1229 * Validate input.
1230 */
1231 AssertMsgReturn(pPicReg->u32Version == PDM_PICREG_VERSION,
1232 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32Version, PDM_PICREG_VERSION),
1233 VERR_VERSION_MISMATCH);
1234 AssertPtrReturn(pPicReg->pfnSetIrq, VERR_INVALID_POINTER);
1235 AssertPtrReturn(pPicReg->pfnGetInterrupt, VERR_INVALID_POINTER);
1236 AssertMsgReturn(pPicReg->u32TheEnd == PDM_PICREG_VERSION,
1237 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32TheEnd, PDM_PICREG_VERSION),
1238 VERR_VERSION_MISMATCH);
1239 AssertPtrReturn(ppPicHlp, VERR_INVALID_POINTER);
1240
1241 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1242 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
1243
1244 /* Check that it's the same device as made the ring-3 registrations: */
1245 AssertLogRelMsgReturn(pGVM->pdm.s.Pic.pDevInsR3 == pDevIns->pDevInsForR3,
1246 ("%p vs %p\n", pGVM->pdm.s.Pic.pDevInsR3, pDevIns->pDevInsForR3), VERR_NOT_OWNER);
1247
1248 /* Check that it isn't already registered in ring-0: */
1249 AssertLogRelMsgReturn(pGVM->pdm.s.Pic.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.Pic.pDevInsR0, pDevIns),
1250 VERR_ALREADY_EXISTS);
1251
1252 /*
1253 * Take down the callbacks and instance.
1254 */
1255 pGVM->pdm.s.Pic.pDevInsR0 = pDevIns;
1256 pGVM->pdm.s.Pic.pfnSetIrqR0 = pPicReg->pfnSetIrq;
1257 pGVM->pdm.s.Pic.pfnGetInterruptR0 = pPicReg->pfnGetInterrupt;
1258 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
1259
1260 /* set the helper pointer and return. */
1261 *ppPicHlp = &g_pdmR0PicHlp;
1262 LogFlow(("pdmR0DevHlp_PICSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
1263 return VINF_SUCCESS;
1264}
1265
1266
1267/** @interface_method_impl{PDMDEVHLPR0,pfnApicSetUpContext} */
1268static DECLCALLBACK(int) pdmR0DevHlp_ApicSetUpContext(PPDMDEVINS pDevIns)
1269{
1270 PDMDEV_ASSERT_DEVINS(pDevIns);
1271 LogFlow(("pdmR0DevHlp_ApicSetUpContext: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
1272 PGVM pGVM = pDevIns->Internal.s.pGVM;
1273
1274 /*
1275 * Validate input.
1276 */
1277 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1278 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
1279
1280 /* Check that it's the same device as made the ring-3 registrations: */
1281 AssertLogRelMsgReturn(pGVM->pdm.s.Apic.pDevInsR3 == pDevIns->pDevInsForR3,
1282 ("%p vs %p\n", pGVM->pdm.s.Apic.pDevInsR3, pDevIns->pDevInsForR3), VERR_NOT_OWNER);
1283
1284 /* Check that it isn't already registered in ring-0: */
1285 AssertLogRelMsgReturn(pGVM->pdm.s.Apic.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.Apic.pDevInsR0, pDevIns),
1286 VERR_ALREADY_EXISTS);
1287
1288 /*
1289 * Take down the instance.
1290 */
1291 pGVM->pdm.s.Apic.pDevInsR0 = pDevIns;
1292 Log(("PDM: Registered APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
1293
1294 /* set the helper pointer and return. */
1295 LogFlow(("pdmR0DevHlp_ApicSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
1296 return VINF_SUCCESS;
1297}
1298
1299
1300/** @interface_method_impl{PDMDEVHLPR0,pfnIoApicSetUpContext} */
1301static DECLCALLBACK(int) pdmR0DevHlp_IoApicSetUpContext(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
1302{
1303 PDMDEV_ASSERT_DEVINS(pDevIns);
1304 LogFlow(("pdmR0DevHlp_IoApicSetUpContext: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnSendMsi=%p, .pfnSetEoi=%p, .u32TheEnd=%#x } ppIoApicHlp=%p\n",
1305 pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrq, pIoApicReg->pfnSendMsi, pIoApicReg->pfnSetEoi, pIoApicReg->u32TheEnd, ppIoApicHlp));
1306 PGVM pGVM = pDevIns->Internal.s.pGVM;
1307
1308 /*
1309 * Validate input.
1310 */
1311 AssertMsgReturn(pIoApicReg->u32Version == PDM_IOAPICREG_VERSION,
1312 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32Version, PDM_IOAPICREG_VERSION),
1313 VERR_VERSION_MISMATCH);
1314 AssertPtrReturn(pIoApicReg->pfnSetIrq, VERR_INVALID_POINTER);
1315 AssertPtrReturn(pIoApicReg->pfnSendMsi, VERR_INVALID_POINTER);
1316 AssertPtrReturn(pIoApicReg->pfnSetEoi, VERR_INVALID_POINTER);
1317 AssertMsgReturn(pIoApicReg->u32TheEnd == PDM_IOAPICREG_VERSION,
1318 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32TheEnd, PDM_IOAPICREG_VERSION),
1319 VERR_VERSION_MISMATCH);
1320 AssertPtrReturn(ppIoApicHlp, VERR_INVALID_POINTER);
1321
1322 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1323 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
1324
1325 /* Check that it's the same device as made the ring-3 registrations: */
1326 AssertLogRelMsgReturn(pGVM->pdm.s.IoApic.pDevInsR3 == pDevIns->pDevInsForR3,
1327 ("%p vs %p\n", pGVM->pdm.s.IoApic.pDevInsR3, pDevIns->pDevInsForR3), VERR_NOT_OWNER);
1328
1329 /* Check that it isn't already registered in ring-0: */
1330 AssertLogRelMsgReturn(pGVM->pdm.s.IoApic.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.IoApic.pDevInsR0, pDevIns),
1331 VERR_ALREADY_EXISTS);
1332
1333 /*
1334 * Take down the callbacks and instance.
1335 */
1336 pGVM->pdm.s.IoApic.pDevInsR0 = pDevIns;
1337 pGVM->pdm.s.IoApic.pfnSetIrqR0 = pIoApicReg->pfnSetIrq;
1338 pGVM->pdm.s.IoApic.pfnSendMsiR0 = pIoApicReg->pfnSendMsi;
1339 pGVM->pdm.s.IoApic.pfnSetEoiR0 = pIoApicReg->pfnSetEoi;
1340 Log(("PDM: Registered IOAPIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
1341
1342 /* set the helper pointer and return. */
1343 *ppIoApicHlp = &g_pdmR0IoApicHlp;
1344 LogFlow(("pdmR0DevHlp_IoApicSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
1345 return VINF_SUCCESS;
1346}
1347
1348
1349/** @interface_method_impl{PDMDEVHLPR0,pfnHpetSetUpContext} */
1350static DECLCALLBACK(int) pdmR0DevHlp_HpetSetUpContext(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR0 *ppHpetHlp)
1351{
1352 PDMDEV_ASSERT_DEVINS(pDevIns);
1353 LogFlow(("pdmR0DevHlp_HpetSetUpContext: caller='%s'/%d: pHpetReg=%p:{.u32Version=%#x, } ppHpetHlp=%p\n",
1354 pDevIns->pReg->szName, pDevIns->iInstance, pHpetReg, pHpetReg->u32Version, ppHpetHlp));
1355 PGVM pGVM = pDevIns->Internal.s.pGVM;
1356
1357 /*
1358 * Validate input.
1359 */
1360 AssertMsgReturn(pHpetReg->u32Version == PDM_HPETREG_VERSION,
1361 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pHpetReg->u32Version, PDM_HPETREG_VERSION),
1362 VERR_VERSION_MISMATCH);
1363 AssertPtrReturn(ppHpetHlp, VERR_INVALID_POINTER);
1364
1365 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
1366 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
1367
1368 /* Check that it's the same device as made the ring-3 registrations: */
1369 AssertLogRelMsgReturn(pGVM->pdm.s.pHpet == pDevIns->pDevInsForR3, ("%p vs %p\n", pGVM->pdm.s.pHpet, pDevIns->pDevInsForR3),
1370 VERR_NOT_OWNER);
1371
1372 ///* Check that it isn't already registered in ring-0: */
1373 //AssertLogRelMsgReturn(pGVM->pdm.s.Hpet.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.Hpet.pDevInsR0, pDevIns),
1374 // VERR_ALREADY_EXISTS);
1375
1376 /*
1377 * Nothing to take down here at present.
1378 */
1379 Log(("PDM: Registered HPET device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
1380
1381 /* set the helper pointer and return. */
1382 *ppHpetHlp = &g_pdmR0HpetHlp;
1383 LogFlow(("pdmR0DevHlp_HpetSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
1384 return VINF_SUCCESS;
1385}
1386
1387
1388/**
1389 * The Ring-0 Device Helper Callbacks.
1390 */
1391extern DECLEXPORT(const PDMDEVHLPR0) g_pdmR0DevHlp =
1392{
1393 PDM_DEVHLPR0_VERSION,
1394 pdmR0DevHlp_IoPortSetUpContextEx,
1395 pdmR0DevHlp_MmioSetUpContextEx,
1396 pdmR0DevHlp_Mmio2SetUpContext,
1397 pdmR0DevHlp_PCIPhysRead,
1398 pdmR0DevHlp_PCIPhysWrite,
1399 pdmR0DevHlp_PCISetIrq,
1400 pdmR0DevHlp_ISASetIrq,
1401 pdmR0DevHlp_IoApicSendMsi,
1402 pdmR0DevHlp_PhysRead,
1403 pdmR0DevHlp_PhysWrite,
1404 pdmR0DevHlp_A20IsEnabled,
1405 pdmR0DevHlp_VMState,
1406 pdmR0DevHlp_VMSetError,
1407 pdmR0DevHlp_VMSetErrorV,
1408 pdmR0DevHlp_VMSetRuntimeError,
1409 pdmR0DevHlp_VMSetRuntimeErrorV,
1410 pdmR0DevHlp_GetVM,
1411 pdmR0DevHlp_GetVMCPU,
1412 pdmR0DevHlp_GetCurrentCpuId,
1413 pdmR0DevHlp_TimerToPtr,
1414 pdmR0DevHlp_TimerFromMicro,
1415 pdmR0DevHlp_TimerFromMilli,
1416 pdmR0DevHlp_TimerFromNano,
1417 pdmR0DevHlp_TimerGet,
1418 pdmR0DevHlp_TimerGetFreq,
1419 pdmR0DevHlp_TimerGetNano,
1420 pdmR0DevHlp_TimerIsActive,
1421 pdmR0DevHlp_TimerIsLockOwner,
1422 pdmR0DevHlp_TimerLockClock,
1423 pdmR0DevHlp_TimerLockClock2,
1424 pdmR0DevHlp_TimerSet,
1425 pdmR0DevHlp_TimerSetFrequencyHint,
1426 pdmR0DevHlp_TimerSetMicro,
1427 pdmR0DevHlp_TimerSetMillies,
1428 pdmR0DevHlp_TimerSetNano,
1429 pdmR0DevHlp_TimerSetRelative,
1430 pdmR0DevHlp_TimerStop,
1431 pdmR0DevHlp_TimerUnlockClock,
1432 pdmR0DevHlp_TimerUnlockClock2,
1433 pdmR0DevHlp_TMTimeVirtGet,
1434 pdmR0DevHlp_TMTimeVirtGetFreq,
1435 pdmR0DevHlp_TMTimeVirtGetNano,
1436 pdmR0DevHlp_QueueToPtr,
1437 pdmR0DevHlp_QueueAlloc,
1438 pdmR0DevHlp_QueueInsert,
1439 pdmR0DevHlp_QueueInsertEx,
1440 pdmR0DevHlp_QueueFlushIfNecessary,
1441 pdmR0DevHlp_TaskTrigger,
1442 pdmR0DevHlp_SUPSemEventSignal,
1443 pdmR0DevHlp_SUPSemEventWaitNoResume,
1444 pdmR0DevHlp_SUPSemEventWaitNsAbsIntr,
1445 pdmR0DevHlp_SUPSemEventWaitNsRelIntr,
1446 pdmR0DevHlp_SUPSemEventGetResolution,
1447 pdmR0DevHlp_SUPSemEventMultiSignal,
1448 pdmR0DevHlp_SUPSemEventMultiReset,
1449 pdmR0DevHlp_SUPSemEventMultiWaitNoResume,
1450 pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr,
1451 pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr,
1452 pdmR0DevHlp_SUPSemEventMultiGetResolution,
1453 pdmR0DevHlp_CritSectGetNop,
1454 pdmR0DevHlp_SetDeviceCritSect,
1455 pdmR0DevHlp_CritSectEnter,
1456 pdmR0DevHlp_CritSectEnterDebug,
1457 pdmR0DevHlp_CritSectTryEnter,
1458 pdmR0DevHlp_CritSectTryEnterDebug,
1459 pdmR0DevHlp_CritSectLeave,
1460 pdmR0DevHlp_CritSectIsOwner,
1461 pdmR0DevHlp_CritSectIsInitialized,
1462 pdmR0DevHlp_CritSectHasWaiters,
1463 pdmR0DevHlp_CritSectGetRecursion,
1464 pdmR0DevHlp_CritSectScheduleExitEvent,
1465 pdmR0DevHlp_DBGFTraceBuf,
1466 pdmR0DevHlp_PCIBusSetUpContext,
1467 pdmR0DevHlp_IommuSetUpContext,
1468 pdmR0DevHlp_PICSetUpContext,
1469 pdmR0DevHlp_ApicSetUpContext,
1470 pdmR0DevHlp_IoApicSetUpContext,
1471 pdmR0DevHlp_HpetSetUpContext,
1472 NULL /*pfnReserved1*/,
1473 NULL /*pfnReserved2*/,
1474 NULL /*pfnReserved3*/,
1475 NULL /*pfnReserved4*/,
1476 NULL /*pfnReserved5*/,
1477 NULL /*pfnReserved6*/,
1478 NULL /*pfnReserved7*/,
1479 NULL /*pfnReserved8*/,
1480 NULL /*pfnReserved9*/,
1481 NULL /*pfnReserved10*/,
1482 PDM_DEVHLPR0_VERSION
1483};
1484
1485/** @} */
1486
1487
1488
1489
1490/** @name PIC Ring-0 Helpers
1491 * @{
1492 */
1493
1494/** @interface_method_impl{PDMPICHLP,pfnSetInterruptFF} */
1495static DECLCALLBACK(void) pdmR0PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
1496{
1497 PDMDEV_ASSERT_DEVINS(pDevIns);
1498 PGVM pGVM = (PGVM)pDevIns->Internal.s.pGVM;
1499 PVMCPUCC pVCpu = &pGVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
1500 /** @todo r=ramshankar: Propagating rcRZ and make all callers handle it? */
1501 APICLocalInterrupt(pVCpu, 0 /* u8Pin */, 1 /* u8Level */, VINF_SUCCESS /* rcRZ */);
1502}
1503
1504
1505/** @interface_method_impl{PDMPICHLP,pfnClearInterruptFF} */
1506static DECLCALLBACK(void) pdmR0PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
1507{
1508 PDMDEV_ASSERT_DEVINS(pDevIns);
1509 PGVM pGVM = (PGVM)pDevIns->Internal.s.pGVM;
1510 PVMCPUCC pVCpu = &pGVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
1511 /** @todo r=ramshankar: Propagating rcRZ and make all callers handle it? */
1512 APICLocalInterrupt(pVCpu, 0 /* u8Pin */, 0 /* u8Level */, VINF_SUCCESS /* rcRZ */);
1513}
1514
1515
1516/** @interface_method_impl{PDMPICHLP,pfnLock} */
1517static DECLCALLBACK(int) pdmR0PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
1518{
1519 PDMDEV_ASSERT_DEVINS(pDevIns);
1520 return pdmLockEx(pDevIns->Internal.s.pGVM, rc);
1521}
1522
1523
1524/** @interface_method_impl{PDMPICHLP,pfnUnlock} */
1525static DECLCALLBACK(void) pdmR0PicHlp_Unlock(PPDMDEVINS pDevIns)
1526{
1527 PDMDEV_ASSERT_DEVINS(pDevIns);
1528 pdmUnlock(pDevIns->Internal.s.pGVM);
1529}
1530
1531
1532/**
1533 * The Ring-0 PIC Helper Callbacks.
1534 */
1535extern DECLEXPORT(const PDMPICHLP) g_pdmR0PicHlp =
1536{
1537 PDM_PICHLP_VERSION,
1538 pdmR0PicHlp_SetInterruptFF,
1539 pdmR0PicHlp_ClearInterruptFF,
1540 pdmR0PicHlp_Lock,
1541 pdmR0PicHlp_Unlock,
1542 PDM_PICHLP_VERSION
1543};
1544
1545/** @} */
1546
1547
1548/** @name I/O APIC Ring-0 Helpers
1549 * @{
1550 */
1551
1552/** @interface_method_impl{PDMIOAPICHLP,pfnApicBusDeliver} */
1553static DECLCALLBACK(int) pdmR0IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode,
1554 uint8_t u8DeliveryMode, uint8_t uVector, uint8_t u8Polarity,
1555 uint8_t u8TriggerMode, uint32_t uTagSrc)
1556{
1557 PDMDEV_ASSERT_DEVINS(pDevIns);
1558 PGVM pGVM = pDevIns->Internal.s.pGVM;
1559 LogFlow(("pdmR0IoApicHlp_ApicBusDeliver: caller=%p/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 uVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8 uTagSrc=%#x\n",
1560 pDevIns, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, uVector, u8Polarity, u8TriggerMode, uTagSrc));
1561 return APICBusDeliver(pGVM, u8Dest, u8DestMode, u8DeliveryMode, uVector, u8Polarity, u8TriggerMode, uTagSrc);
1562}
1563
1564
1565/** @interface_method_impl{PDMIOAPICHLP,pfnLock} */
1566static DECLCALLBACK(int) pdmR0IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
1567{
1568 PDMDEV_ASSERT_DEVINS(pDevIns);
1569 return pdmLockEx(pDevIns->Internal.s.pGVM, rc);
1570}
1571
1572
1573/** @interface_method_impl{PDMIOAPICHLP,pfnUnlock} */
1574static DECLCALLBACK(void) pdmR0IoApicHlp_Unlock(PPDMDEVINS pDevIns)
1575{
1576 PDMDEV_ASSERT_DEVINS(pDevIns);
1577 pdmUnlock(pDevIns->Internal.s.pGVM);
1578}
1579
1580
1581/**
1582 * The Ring-0 I/O APIC Helper Callbacks.
1583 */
1584extern DECLEXPORT(const PDMIOAPICHLP) g_pdmR0IoApicHlp =
1585{
1586 PDM_IOAPICHLP_VERSION,
1587 pdmR0IoApicHlp_ApicBusDeliver,
1588 pdmR0IoApicHlp_Lock,
1589 pdmR0IoApicHlp_Unlock,
1590 PDM_IOAPICHLP_VERSION
1591};
1592
1593/** @} */
1594
1595
1596
1597
1598/** @name PCI Bus Ring-0 Helpers
1599 * @{
1600 */
1601
1602/** @interface_method_impl{PDMPCIHLPR0,pfnIsaSetIrq} */
1603static DECLCALLBACK(void) pdmR0PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
1604{
1605 PDMDEV_ASSERT_DEVINS(pDevIns);
1606 Log4(("pdmR0PciHlp_IsaSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
1607 PGVM pGVM = pDevIns->Internal.s.pGVM;
1608
1609 pdmLock(pGVM);
1610 pdmR0IsaSetIrq(pGVM, iIrq, iLevel, uTagSrc);
1611 pdmUnlock(pGVM);
1612}
1613
1614
1615/** @interface_method_impl{PDMPCIHLPR0,pfnIoApicSetIrq} */
1616static DECLCALLBACK(void) pdmR0PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
1617{
1618 PDMDEV_ASSERT_DEVINS(pDevIns);
1619 Log4(("pdmR0PciHlp_IoApicSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
1620 PGVM pGVM = pDevIns->Internal.s.pGVM;
1621
1622 if (pGVM->pdm.s.IoApic.pDevInsR0)
1623 pGVM->pdm.s.IoApic.pfnSetIrqR0(pGVM->pdm.s.IoApic.pDevInsR0, iIrq, iLevel, uTagSrc);
1624 else if (pGVM->pdm.s.IoApic.pDevInsR3)
1625 {
1626 /* queue for ring-3 execution. */
1627 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM->pdm.s.pDevHlpQueueR0);
1628 if (pTask)
1629 {
1630 pTask->enmOp = PDMDEVHLPTASKOP_IOAPIC_SET_IRQ;
1631 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
1632 pTask->u.IoApicSetIRQ.iIrq = iIrq;
1633 pTask->u.IoApicSetIRQ.iLevel = iLevel;
1634 pTask->u.IoApicSetIRQ.uTagSrc = uTagSrc;
1635
1636 PDMQueueInsertEx(pGVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
1637 }
1638 else
1639 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
1640 }
1641}
1642
1643
1644/** @interface_method_impl{PDMPCIHLPR0,pfnIoApicSendMsi} */
1645static DECLCALLBACK(void) pdmR0PciHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc)
1646{
1647 PDMDEV_ASSERT_DEVINS(pDevIns);
1648 Log4(("pdmR0PciHlp_IoApicSendMsi: GCPhys=%p uValue=%d uTagSrc=%#x\n", GCPhys, uValue, uTagSrc));
1649 PGVM pGVM = pDevIns->Internal.s.pGVM;
1650 if (pGVM->pdm.s.IoApic.pDevInsR0)
1651 pGVM->pdm.s.IoApic.pfnSendMsiR0(pGVM->pdm.s.IoApic.pDevInsR0, GCPhys, uValue, uTagSrc);
1652 else
1653 AssertFatalMsgFailed(("Lazy bastards!"));
1654}
1655
1656
1657/** @interface_method_impl{PDMPCIHLPR0,pfnLock} */
1658static DECLCALLBACK(int) pdmR0PciHlp_Lock(PPDMDEVINS pDevIns, int rc)
1659{
1660 PDMDEV_ASSERT_DEVINS(pDevIns);
1661 return pdmLockEx(pDevIns->Internal.s.pGVM, rc);
1662}
1663
1664
1665/** @interface_method_impl{PDMPCIHLPR0,pfnUnlock} */
1666static DECLCALLBACK(void) pdmR0PciHlp_Unlock(PPDMDEVINS pDevIns)
1667{
1668 PDMDEV_ASSERT_DEVINS(pDevIns);
1669 pdmUnlock(pDevIns->Internal.s.pGVM);
1670}
1671
1672
1673/** @interface_method_impl{PDMPCIHLPR0,pfnGetBusByNo} */
1674static DECLCALLBACK(PPDMDEVINS) pdmR0PciHlp_GetBusByNo(PPDMDEVINS pDevIns, uint32_t idxPdmBus)
1675{
1676 PDMDEV_ASSERT_DEVINS(pDevIns);
1677 PGVM pGVM = pDevIns->Internal.s.pGVM;
1678 AssertReturn(idxPdmBus < RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses), NULL);
1679 PPDMDEVINS pRetDevIns = pGVM->pdmr0.s.aPciBuses[idxPdmBus].pDevInsR0;
1680 LogFlow(("pdmR3PciHlp_GetBusByNo: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pRetDevIns));
1681 return pRetDevIns;
1682}
1683
1684
1685/**
1686 * The Ring-0 PCI Bus Helper Callbacks.
1687 */
1688extern DECLEXPORT(const PDMPCIHLPR0) g_pdmR0PciHlp =
1689{
1690 PDM_PCIHLPR0_VERSION,
1691 pdmR0PciHlp_IsaSetIrq,
1692 pdmR0PciHlp_IoApicSetIrq,
1693 pdmR0PciHlp_IoApicSendMsi,
1694 pdmR0PciHlp_Lock,
1695 pdmR0PciHlp_Unlock,
1696 pdmR0PciHlp_GetBusByNo,
1697 PDM_PCIHLPR0_VERSION, /* the end */
1698};
1699
1700/** @} */
1701
1702
1703/** @name IOMMU Ring-0 Helpers
1704 * @{
1705 */
1706
1707/**
1708 * The Ring-0 IOMMU Helper Callbacks.
1709 */
1710extern DECLEXPORT(const PDMIOMMUHLPR0) g_pdmR0IommuHlp =
1711{
1712 PDM_IOMMUHLPR0_VERSION,
1713 PDM_IOMMUHLPR0_VERSION, /* the end */
1714};
1715
1716/** @} */
1717
1718
1719/** @name HPET Ring-0 Helpers
1720 * @{
1721 */
1722/* none */
1723
1724/**
1725 * The Ring-0 HPET Helper Callbacks.
1726 */
1727extern DECLEXPORT(const PDMHPETHLPR0) g_pdmR0HpetHlp =
1728{
1729 PDM_HPETHLPR0_VERSION,
1730 PDM_HPETHLPR0_VERSION, /* the end */
1731};
1732
1733/** @} */
1734
1735
1736/** @name Raw PCI Ring-0 Helpers
1737 * @{
1738 */
1739/* none */
1740
1741/**
1742 * The Ring-0 PCI raw Helper Callbacks.
1743 */
1744extern DECLEXPORT(const PDMPCIRAWHLPR0) g_pdmR0PciRawHlp =
1745{
1746 PDM_PCIRAWHLPR0_VERSION,
1747 PDM_PCIRAWHLPR0_VERSION, /* the end */
1748};
1749
1750/** @} */
1751
1752
1753/** @name Ring-0 Context Driver Helpers
1754 * @{
1755 */
1756
1757/** @interface_method_impl{PDMDRVHLPR0,pfnVMSetError} */
1758static DECLCALLBACK(int) pdmR0DrvHlp_VMSetError(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
1759{
1760 PDMDRV_ASSERT_DRVINS(pDrvIns);
1761 va_list args;
1762 va_start(args, pszFormat);
1763 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMR0, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
1764 va_end(args);
1765 return rc;
1766}
1767
1768
1769/** @interface_method_impl{PDMDRVHLPR0,pfnVMSetErrorV} */
1770static DECLCALLBACK(int) pdmR0DrvHlp_VMSetErrorV(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
1771{
1772 PDMDRV_ASSERT_DRVINS(pDrvIns);
1773 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMR0, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
1774 return rc;
1775}
1776
1777
1778/** @interface_method_impl{PDMDRVHLPR0,pfnVMSetRuntimeError} */
1779static DECLCALLBACK(int) pdmR0DrvHlp_VMSetRuntimeError(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId,
1780 const char *pszFormat, ...)
1781{
1782 PDMDRV_ASSERT_DRVINS(pDrvIns);
1783 va_list va;
1784 va_start(va, pszFormat);
1785 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMR0, fFlags, pszErrorId, pszFormat, va);
1786 va_end(va);
1787 return rc;
1788}
1789
1790
1791/** @interface_method_impl{PDMDRVHLPR0,pfnVMSetRuntimeErrorV} */
1792static DECLCALLBACK(int) pdmR0DrvHlp_VMSetRuntimeErrorV(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId,
1793 const char *pszFormat, va_list va)
1794{
1795 PDMDRV_ASSERT_DRVINS(pDrvIns);
1796 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMR0, fFlags, pszErrorId, pszFormat, va);
1797 return rc;
1798}
1799
1800
1801/** @interface_method_impl{PDMDRVHLPR0,pfnAssertEMT} */
1802static DECLCALLBACK(bool) pdmR0DrvHlp_AssertEMT(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
1803{
1804 PDMDRV_ASSERT_DRVINS(pDrvIns);
1805 if (VM_IS_EMT(pDrvIns->Internal.s.pVMR0))
1806 return true;
1807
1808 RTAssertMsg1Weak("AssertEMT", iLine, pszFile, pszFunction);
1809 RTAssertPanic();
1810 return false;
1811}
1812
1813
1814/** @interface_method_impl{PDMDRVHLPR0,pfnAssertOther} */
1815static DECLCALLBACK(bool) pdmR0DrvHlp_AssertOther(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
1816{
1817 PDMDRV_ASSERT_DRVINS(pDrvIns);
1818 if (!VM_IS_EMT(pDrvIns->Internal.s.pVMR0))
1819 return true;
1820
1821 RTAssertMsg1Weak("AssertOther", iLine, pszFile, pszFunction);
1822 RTAssertPanic();
1823 return false;
1824}
1825
1826
1827/**
1828 * The Ring-0 Context Driver Helper Callbacks.
1829 */
1830extern DECLEXPORT(const PDMDRVHLPR0) g_pdmR0DrvHlp =
1831{
1832 PDM_DRVHLPRC_VERSION,
1833 pdmR0DrvHlp_VMSetError,
1834 pdmR0DrvHlp_VMSetErrorV,
1835 pdmR0DrvHlp_VMSetRuntimeError,
1836 pdmR0DrvHlp_VMSetRuntimeErrorV,
1837 pdmR0DrvHlp_AssertEMT,
1838 pdmR0DrvHlp_AssertOther,
1839 PDM_DRVHLPRC_VERSION
1840};
1841
1842/** @} */
1843
1844
1845
1846
1847/**
1848 * Sets an irq on the PIC and I/O APIC.
1849 *
1850 * @returns true if delivered, false if postponed.
1851 * @param pGVM The global (ring-0) VM structure.
1852 * @param iIrq The irq.
1853 * @param iLevel The new level.
1854 * @param uTagSrc The IRQ tag and source.
1855 *
1856 * @remarks The caller holds the PDM lock.
1857 */
1858static bool pdmR0IsaSetIrq(PGVM pGVM, int iIrq, int iLevel, uint32_t uTagSrc)
1859{
1860 if (RT_LIKELY( ( pGVM->pdm.s.IoApic.pDevInsR0
1861 || !pGVM->pdm.s.IoApic.pDevInsR3)
1862 && ( pGVM->pdm.s.Pic.pDevInsR0
1863 || !pGVM->pdm.s.Pic.pDevInsR3)))
1864 {
1865 if (pGVM->pdm.s.Pic.pDevInsR0)
1866 pGVM->pdm.s.Pic.pfnSetIrqR0(pGVM->pdm.s.Pic.pDevInsR0, iIrq, iLevel, uTagSrc);
1867 if (pGVM->pdm.s.IoApic.pDevInsR0)
1868 pGVM->pdm.s.IoApic.pfnSetIrqR0(pGVM->pdm.s.IoApic.pDevInsR0, iIrq, iLevel, uTagSrc);
1869 return true;
1870 }
1871
1872 /* queue for ring-3 execution. */
1873 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM->pdm.s.pDevHlpQueueR0);
1874 AssertReturn(pTask, false);
1875
1876 pTask->enmOp = PDMDEVHLPTASKOP_ISA_SET_IRQ;
1877 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
1878 pTask->u.IsaSetIRQ.iIrq = iIrq;
1879 pTask->u.IsaSetIRQ.iLevel = iLevel;
1880 pTask->u.IsaSetIRQ.uTagSrc = uTagSrc;
1881
1882 PDMQueueInsertEx(pGVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
1883 return false;
1884}
1885
1886
1887/**
1888 * Worker for PDMR0DeviceCreate that does the actual instantiation.
1889 *
1890 * Allocates a memory object and divides it up as follows:
1891 * @verbatim
1892 --------------------------------------
1893 ring-0 devins
1894 --------------------------------------
1895 ring-0 instance data
1896 --------------------------------------
1897 ring-0 PCI device data (optional) ??
1898 --------------------------------------
1899 page alignment padding
1900 --------------------------------------
1901 ring-3 devins
1902 --------------------------------------
1903 ring-3 instance data
1904 --------------------------------------
1905 ring-3 PCI device data (optional) ??
1906 --------------------------------------
1907 [page alignment padding ] -
1908 [--------------------------------------] \
1909 [raw-mode devins ] \
1910 [--------------------------------------] - Optional, only when raw-mode is enabled.
1911 [raw-mode instance data ] /
1912 [--------------------------------------] /
1913 [raw-mode PCI device data (optional)?? ] -
1914 --------------------------------------
1915 shared instance data
1916 --------------------------------------
1917 default crit section
1918 --------------------------------------
1919 shared PCI device data (optional)
1920 --------------------------------------
1921 @endverbatim
1922 *
1923 * @returns VBox status code.
1924 * @param pGVM The global (ring-0) VM structure.
1925 * @param pDevReg The device registration structure.
1926 * @param iInstance The device instance number.
1927 * @param cbInstanceR3 The size of the ring-3 instance data.
1928 * @param cbInstanceRC The size of the raw-mode instance data.
1929 * @param hMod The module implementing the device. On success, the
1930 * @param RCPtrMapping The raw-mode context mapping address, NIL_RTGCPTR if
1931 * not to include raw-mode.
1932 * @param ppDevInsR3 Where to return the ring-3 device instance address.
1933 * @thread EMT(0)
1934 */
1935static int pdmR0DeviceCreateWorker(PGVM pGVM, PCPDMDEVREGR0 pDevReg, uint32_t iInstance, uint32_t cbInstanceR3,
1936 uint32_t cbInstanceRC, RTRGPTR RCPtrMapping, void *hMod, PPDMDEVINSR3 *ppDevInsR3)
1937{
1938 /*
1939 * Check that the instance number isn't a duplicate.
1940 */
1941 for (size_t i = 0; i < pGVM->pdmr0.s.cDevInstances; i++)
1942 {
1943 PPDMDEVINS pCur = pGVM->pdmr0.s.apDevInstances[i];
1944 AssertLogRelReturn(!pCur || pCur->pReg != pDevReg || pCur->iInstance != iInstance, VERR_DUPLICATE);
1945 }
1946
1947 /*
1948 * Figure out how much memory we need and allocate it.
1949 */
1950 uint32_t const cbRing0 = RT_ALIGN_32(RT_UOFFSETOF(PDMDEVINSR0, achInstanceData) + pDevReg->cbInstanceCC, PAGE_SIZE);
1951 uint32_t const cbRing3 = RT_ALIGN_32(RT_UOFFSETOF(PDMDEVINSR3, achInstanceData) + cbInstanceR3,
1952 RCPtrMapping != NIL_RTRGPTR ? PAGE_SIZE : 64);
1953 uint32_t const cbRC = RCPtrMapping != NIL_RTRGPTR ? 0
1954 : RT_ALIGN_32(RT_UOFFSETOF(PDMDEVINSRC, achInstanceData) + cbInstanceRC, 64);
1955 uint32_t const cbShared = RT_ALIGN_32(pDevReg->cbInstanceShared, 64);
1956 uint32_t const cbCritSect = RT_ALIGN_32(sizeof(PDMCRITSECT), 64);
1957 uint32_t const cbMsixState = RT_ALIGN_32(pDevReg->cMaxMsixVectors * 16 + (pDevReg->cMaxMsixVectors + 7) / 8, _4K);
1958 uint32_t const cbPciDev = RT_ALIGN_32(RT_UOFFSETOF_DYN(PDMPCIDEV, abMsixState[cbMsixState]), 64);
1959 uint32_t const cPciDevs = RT_MIN(pDevReg->cMaxPciDevices, 8);
1960 uint32_t const cbPciDevs = cbPciDev * cPciDevs;
1961 uint32_t const cbTotal = RT_ALIGN_32(cbRing0 + cbRing3 + cbRC + cbShared + cbCritSect + cbPciDevs, PAGE_SIZE);
1962 AssertLogRelMsgReturn(cbTotal <= PDM_MAX_DEVICE_INSTANCE_SIZE,
1963 ("Instance of '%s' is too big: cbTotal=%u, max %u\n",
1964 pDevReg->szName, cbTotal, PDM_MAX_DEVICE_INSTANCE_SIZE),
1965 VERR_OUT_OF_RANGE);
1966
1967 RTR0MEMOBJ hMemObj;
1968 int rc = RTR0MemObjAllocPage(&hMemObj, cbTotal, false /*fExecutable*/);
1969 if (RT_FAILURE(rc))
1970 return rc;
1971 RT_BZERO(RTR0MemObjAddress(hMemObj), cbTotal);
1972
1973 /* Map it. */
1974 RTR0MEMOBJ hMapObj;
1975 rc = RTR0MemObjMapUserEx(&hMapObj, hMemObj, (RTR3PTR)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE, RTR0ProcHandleSelf(),
1976 cbRing0, cbTotal - cbRing0);
1977 if (RT_SUCCESS(rc))
1978 {
1979 PPDMDEVINSR0 pDevIns = (PPDMDEVINSR0)RTR0MemObjAddress(hMemObj);
1980 struct PDMDEVINSR3 *pDevInsR3 = (struct PDMDEVINSR3 *)((uint8_t *)pDevIns + cbRing0);
1981
1982 /*
1983 * Initialize the ring-0 instance.
1984 */
1985 pDevIns->u32Version = PDM_DEVINSR0_VERSION;
1986 pDevIns->iInstance = iInstance;
1987 pDevIns->pHlpR0 = &g_pdmR0DevHlp;
1988 pDevIns->pvInstanceDataR0 = (uint8_t *)pDevIns + cbRing0 + cbRing3 + cbRC;
1989 pDevIns->pvInstanceDataForR0 = &pDevIns->achInstanceData[0];
1990 pDevIns->pCritSectRoR0 = (PPDMCRITSECT)((uint8_t *)pDevIns->pvInstanceDataR0 + cbShared);
1991 pDevIns->pReg = pDevReg;
1992 pDevIns->pDevInsForR3 = RTR0MemObjAddressR3(hMapObj);
1993 pDevIns->pDevInsForR3R0 = pDevInsR3;
1994 pDevIns->pvInstanceDataForR3R0 = &pDevInsR3->achInstanceData[0];
1995 pDevIns->cbPciDev = cbPciDev;
1996 pDevIns->cPciDevs = cPciDevs;
1997 for (uint32_t iPciDev = 0; iPciDev < cPciDevs; iPciDev++)
1998 {
1999 /* Note! PDMDevice.cpp has a copy of this code. Keep in sync. */
2000 PPDMPCIDEV pPciDev = (PPDMPCIDEV)((uint8_t *)pDevIns->pCritSectRoR0 + cbCritSect + cbPciDev * iPciDev);
2001 if (iPciDev < RT_ELEMENTS(pDevIns->apPciDevs))
2002 pDevIns->apPciDevs[iPciDev] = pPciDev;
2003 pPciDev->cbConfig = _4K;
2004 pPciDev->cbMsixState = cbMsixState;
2005 pPciDev->idxSubDev = (uint16_t)iPciDev;
2006 pPciDev->Int.s.idxSubDev = (uint16_t)iPciDev;
2007 pPciDev->u32Magic = PDMPCIDEV_MAGIC;
2008 }
2009 pDevIns->Internal.s.pGVM = pGVM;
2010 pDevIns->Internal.s.pRegR0 = pDevReg;
2011 pDevIns->Internal.s.hMod = hMod;
2012 pDevIns->Internal.s.hMemObj = hMemObj;
2013 pDevIns->Internal.s.hMapObj = hMapObj;
2014 pDevIns->Internal.s.pInsR3R0 = pDevInsR3;
2015 pDevIns->Internal.s.pIntR3R0 = &pDevInsR3->Internal.s;
2016
2017 /*
2018 * Initialize the ring-3 instance data as much as we can.
2019 * Note! PDMDevice.cpp does this job for ring-3 only devices. Keep in sync.
2020 */
2021 pDevInsR3->u32Version = PDM_DEVINSR3_VERSION;
2022 pDevInsR3->iInstance = iInstance;
2023 pDevInsR3->cbRing3 = cbTotal - cbRing0;
2024 pDevInsR3->fR0Enabled = true;
2025 pDevInsR3->fRCEnabled = RCPtrMapping != NIL_RTRGPTR;
2026 pDevInsR3->pvInstanceDataR3 = pDevIns->pDevInsForR3 + cbRing3 + cbRC;
2027 pDevInsR3->pvInstanceDataForR3 = pDevIns->pDevInsForR3 + RT_UOFFSETOF(PDMDEVINSR3, achInstanceData);
2028 pDevInsR3->pCritSectRoR3 = pDevIns->pDevInsForR3 + cbRing3 + cbRC + cbShared;
2029 pDevInsR3->pDevInsR0RemoveMe = pDevIns;
2030 pDevInsR3->pvInstanceDataR0 = pDevIns->pvInstanceDataR0;
2031 pDevInsR3->pvInstanceDataRC = RCPtrMapping == NIL_RTRGPTR
2032 ? NIL_RTRGPTR : pDevIns->pDevInsForRC + RT_UOFFSETOF(PDMDEVINSRC, achInstanceData);
2033 pDevInsR3->pDevInsForRC = pDevIns->pDevInsForRC;
2034 pDevInsR3->pDevInsForRCR3 = pDevIns->pDevInsForR3 + cbRing3;
2035 pDevInsR3->pDevInsForRCR3 = pDevInsR3->pDevInsForRCR3 + RT_UOFFSETOF(PDMDEVINSRC, achInstanceData);
2036 pDevInsR3->cbPciDev = cbPciDev;
2037 pDevInsR3->cPciDevs = cPciDevs;
2038 for (uint32_t i = 0; i < RT_MIN(cPciDevs, RT_ELEMENTS(pDevIns->apPciDevs)); i++)
2039 pDevInsR3->apPciDevs[i] = pDevInsR3->pCritSectRoR3 + cbCritSect + cbPciDev * i;
2040
2041 pDevInsR3->Internal.s.pVMR3 = pGVM->pVMR3;
2042 pDevInsR3->Internal.s.fIntFlags = RCPtrMapping == NIL_RTRGPTR ? PDMDEVINSINT_FLAGS_R0_ENABLED
2043 : PDMDEVINSINT_FLAGS_R0_ENABLED | PDMDEVINSINT_FLAGS_RC_ENABLED;
2044
2045 /*
2046 * Initialize the raw-mode instance data as much as possible.
2047 */
2048 if (RCPtrMapping != NIL_RTRGPTR)
2049 {
2050 struct PDMDEVINSRC *pDevInsRC = RCPtrMapping == NIL_RTRGPTR ? NULL
2051 : (struct PDMDEVINSRC *)((uint8_t *)pDevIns + cbRing0 + cbRing3);
2052
2053 pDevIns->pDevInsForRC = RCPtrMapping;
2054 pDevIns->pDevInsForRCR0 = pDevInsRC;
2055 pDevIns->pvInstanceDataForRCR0 = &pDevInsRC->achInstanceData[0];
2056
2057 pDevInsRC->u32Version = PDM_DEVINSRC_VERSION;
2058 pDevInsRC->iInstance = iInstance;
2059 pDevInsRC->pvInstanceDataRC = pDevIns->pDevInsForRC + cbRC;
2060 pDevInsRC->pvInstanceDataForRC = pDevIns->pDevInsForRC + RT_UOFFSETOF(PDMDEVINSRC, achInstanceData);
2061 pDevInsRC->pCritSectRoRC = pDevIns->pDevInsForRC + cbRC + cbShared;
2062 pDevInsRC->cbPciDev = cbPciDev;
2063 pDevInsRC->cPciDevs = cPciDevs;
2064 for (uint32_t i = 0; i < RT_MIN(cPciDevs, RT_ELEMENTS(pDevIns->apPciDevs)); i++)
2065 pDevInsRC->apPciDevs[i] = pDevInsRC->pCritSectRoRC + cbCritSect + cbPciDev * i;
2066
2067 pDevInsRC->Internal.s.pVMRC = pGVM->pVMRC;
2068 }
2069
2070 /*
2071 * Add to the device instance array and set its handle value.
2072 */
2073 AssertCompile(sizeof(pGVM->pdmr0.padding) == sizeof(pGVM->pdmr0));
2074 uint32_t idxR0Device = pGVM->pdmr0.s.cDevInstances;
2075 if (idxR0Device < RT_ELEMENTS(pGVM->pdmr0.s.apDevInstances))
2076 {
2077 pGVM->pdmr0.s.apDevInstances[idxR0Device] = pDevIns;
2078 pGVM->pdmr0.s.cDevInstances = idxR0Device + 1;
2079 pDevIns->Internal.s.idxR0Device = idxR0Device;
2080 pDevInsR3->Internal.s.idxR0Device = idxR0Device;
2081
2082 /*
2083 * Call the early constructor if present.
2084 */
2085 if (pDevReg->pfnEarlyConstruct)
2086 rc = pDevReg->pfnEarlyConstruct(pDevIns);
2087 if (RT_SUCCESS(rc))
2088 {
2089 /*
2090 * We're done.
2091 */
2092 *ppDevInsR3 = RTR0MemObjAddressR3(hMapObj);
2093 return rc;
2094 }
2095
2096 /*
2097 * Bail out.
2098 */
2099 if (pDevIns->pReg->pfnFinalDestruct)
2100 pDevIns->pReg->pfnFinalDestruct(pDevIns);
2101
2102 pGVM->pdmr0.s.apDevInstances[idxR0Device] = NULL;
2103 Assert(pGVM->pdmr0.s.cDevInstances == idxR0Device + 1);
2104 pGVM->pdmr0.s.cDevInstances = idxR0Device;
2105 }
2106
2107 RTR0MemObjFree(hMapObj, true);
2108 }
2109 RTR0MemObjFree(hMemObj, true);
2110 return rc;
2111}
2112
2113
2114/**
2115 * Used by ring-3 PDM to create a device instance that operates both in ring-3
2116 * and ring-0.
2117 *
2118 * Creates an instance of a device (for both ring-3 and ring-0, and optionally
2119 * raw-mode context).
2120 *
2121 * @returns VBox status code.
2122 * @param pGVM The global (ring-0) VM structure.
2123 * @param pReq Pointer to the request buffer.
2124 * @thread EMT(0)
2125 */
2126VMMR0_INT_DECL(int) PDMR0DeviceCreateReqHandler(PGVM pGVM, PPDMDEVICECREATEREQ pReq)
2127{
2128 LogFlow(("PDMR0DeviceCreateReqHandler: %s in %s\n", pReq->szDevName, pReq->szModName));
2129
2130 /*
2131 * Validate the request.
2132 */
2133 AssertReturn(pReq->Hdr.cbReq == sizeof(*pReq), VERR_INVALID_PARAMETER);
2134 pReq->pDevInsR3 = NIL_RTR3PTR;
2135
2136 int rc = GVMMR0ValidateGVMandEMT(pGVM, 0);
2137 AssertRCReturn(rc, rc);
2138
2139 AssertReturn(pReq->fFlags != 0, VERR_INVALID_FLAGS);
2140 AssertReturn(pReq->fClass != 0, VERR_WRONG_TYPE);
2141 AssertReturn(pReq->uSharedVersion != 0, VERR_INVALID_PARAMETER);
2142 AssertReturn(pReq->cbInstanceShared != 0, VERR_INVALID_PARAMETER);
2143 size_t const cchDevName = RTStrNLen(pReq->szDevName, sizeof(pReq->szDevName));
2144 AssertReturn(cchDevName < sizeof(pReq->szDevName), VERR_NO_STRING_TERMINATOR);
2145 AssertReturn(cchDevName > 0, VERR_EMPTY_STRING);
2146 AssertReturn(cchDevName < RT_SIZEOFMEMB(PDMDEVREG, szName), VERR_NOT_FOUND);
2147
2148 size_t const cchModName = RTStrNLen(pReq->szModName, sizeof(pReq->szModName));
2149 AssertReturn(cchModName < sizeof(pReq->szModName), VERR_NO_STRING_TERMINATOR);
2150 AssertReturn(cchModName > 0, VERR_EMPTY_STRING);
2151 AssertReturn(pReq->cbInstanceShared <= PDM_MAX_DEVICE_INSTANCE_SIZE, VERR_OUT_OF_RANGE);
2152 AssertReturn(pReq->cbInstanceR3 <= PDM_MAX_DEVICE_INSTANCE_SIZE, VERR_OUT_OF_RANGE);
2153 AssertReturn(pReq->cbInstanceRC <= PDM_MAX_DEVICE_INSTANCE_SIZE, VERR_OUT_OF_RANGE);
2154 AssertReturn(pReq->iInstance < 1024, VERR_OUT_OF_RANGE);
2155 AssertReturn(pReq->iInstance < pReq->cMaxInstances, VERR_OUT_OF_RANGE);
2156 AssertReturn(pReq->cMaxPciDevices <= 8, VERR_OUT_OF_RANGE);
2157 AssertReturn(pReq->cMaxMsixVectors <= VBOX_MSIX_MAX_ENTRIES, VERR_OUT_OF_RANGE);
2158
2159 /*
2160 * Reference the module.
2161 */
2162 void *hMod = NULL;
2163 rc = SUPR0LdrModByName(pGVM->pSession, pReq->szModName, &hMod);
2164 if (RT_FAILURE(rc))
2165 {
2166 LogRel(("PDMR0DeviceCreateReqHandler: SUPR0LdrModByName(,%s,) failed: %Rrc\n", pReq->szModName, rc));
2167 return rc;
2168 }
2169
2170 /*
2171 * Look for the the module and the device registration structure.
2172 */
2173 int rcLock = SUPR0LdrLock(pGVM->pSession);
2174 AssertRC(rc);
2175
2176 rc = VERR_NOT_FOUND;
2177 PPDMDEVMODREGR0 pMod;
2178 RTListForEach(&g_PDMDevModList, pMod, PDMDEVMODREGR0, ListEntry)
2179 {
2180 if (pMod->hMod == hMod)
2181 {
2182 /*
2183 * Found the module. We can drop the loader lock now before we
2184 * search the devices it registers.
2185 */
2186 if (RT_SUCCESS(rcLock))
2187 {
2188 rcLock = SUPR0LdrUnlock(pGVM->pSession);
2189 AssertRC(rcLock);
2190 }
2191 rcLock = VERR_ALREADY_RESET;
2192
2193 PCPDMDEVREGR0 *papDevRegs = pMod->papDevRegs;
2194 size_t i = pMod->cDevRegs;
2195 while (i-- > 0)
2196 {
2197 PCPDMDEVREGR0 pDevReg = papDevRegs[i];
2198 LogFlow(("PDMR0DeviceCreateReqHandler: candidate #%u: %s %#x\n", i, pReq->szDevName, pDevReg->u32Version));
2199 if ( PDM_VERSION_ARE_COMPATIBLE(pDevReg->u32Version, PDM_DEVREGR0_VERSION)
2200 && pDevReg->szName[cchDevName] == '\0'
2201 && memcmp(pDevReg->szName, pReq->szDevName, cchDevName) == 0)
2202 {
2203
2204 /*
2205 * Found the device, now check whether it matches the ring-3 registration.
2206 */
2207 if ( pReq->uSharedVersion == pDevReg->uSharedVersion
2208 && pReq->cbInstanceShared == pDevReg->cbInstanceShared
2209 && pReq->cbInstanceRC == pDevReg->cbInstanceRC
2210 && pReq->fFlags == pDevReg->fFlags
2211 && pReq->fClass == pDevReg->fClass
2212 && pReq->cMaxInstances == pDevReg->cMaxInstances
2213 && pReq->cMaxPciDevices == pDevReg->cMaxPciDevices
2214 && pReq->cMaxMsixVectors == pDevReg->cMaxMsixVectors)
2215 {
2216 rc = pdmR0DeviceCreateWorker(pGVM, pDevReg, pReq->iInstance, pReq->cbInstanceR3, pReq->cbInstanceRC,
2217 NIL_RTRCPTR /** @todo new raw-mode */, hMod, &pReq->pDevInsR3);
2218 if (RT_SUCCESS(rc))
2219 hMod = NULL; /* keep the module reference */
2220 }
2221 else
2222 {
2223 LogRel(("PDMR0DeviceCreate: Ring-3 does not match ring-0 device registration (%s):\n"
2224 " uSharedVersion: %#x vs %#x\n"
2225 " cbInstanceShared: %#x vs %#x\n"
2226 " cbInstanceRC: %#x vs %#x\n"
2227 " fFlags: %#x vs %#x\n"
2228 " fClass: %#x vs %#x\n"
2229 " cMaxInstances: %#x vs %#x\n"
2230 " cMaxPciDevices: %#x vs %#x\n"
2231 " cMaxMsixVectors: %#x vs %#x\n"
2232 ,
2233 pReq->szDevName,
2234 pReq->uSharedVersion, pDevReg->uSharedVersion,
2235 pReq->cbInstanceShared, pDevReg->cbInstanceShared,
2236 pReq->cbInstanceRC, pDevReg->cbInstanceRC,
2237 pReq->fFlags, pDevReg->fFlags,
2238 pReq->fClass, pDevReg->fClass,
2239 pReq->cMaxInstances, pDevReg->cMaxInstances,
2240 pReq->cMaxPciDevices, pDevReg->cMaxPciDevices,
2241 pReq->cMaxMsixVectors, pDevReg->cMaxMsixVectors));
2242 rc = VERR_INCOMPATIBLE_CONFIG;
2243 }
2244 }
2245 }
2246 break;
2247 }
2248 }
2249
2250 if (RT_SUCCESS_NP(rcLock))
2251 {
2252 rcLock = SUPR0LdrUnlock(pGVM->pSession);
2253 AssertRC(rcLock);
2254 }
2255 SUPR0LdrModRelease(pGVM->pSession, hMod);
2256 return rc;
2257}
2258
2259
2260/**
2261 * Used by ring-3 PDM to call standard ring-0 device methods.
2262 *
2263 * @returns VBox status code.
2264 * @param pGVM The global (ring-0) VM structure.
2265 * @param pReq Pointer to the request buffer.
2266 * @param idCpu The ID of the calling EMT.
2267 * @thread EMT(0), except for PDMDEVICEGENCALL_REQUEST which can be any EMT.
2268 */
2269VMMR0_INT_DECL(int) PDMR0DeviceGenCallReqHandler(PGVM pGVM, PPDMDEVICEGENCALLREQ pReq, VMCPUID idCpu)
2270{
2271 /*
2272 * Validate the request.
2273 */
2274 AssertReturn(pReq->Hdr.cbReq == sizeof(*pReq), VERR_INVALID_PARAMETER);
2275
2276 int rc = GVMMR0ValidateGVMandEMT(pGVM, idCpu);
2277 AssertRCReturn(rc, rc);
2278
2279 AssertReturn(pReq->idxR0Device < pGVM->pdmr0.s.cDevInstances, VERR_INVALID_HANDLE);
2280 PPDMDEVINSR0 pDevIns = pGVM->pdmr0.s.apDevInstances[pReq->idxR0Device];
2281 AssertPtrReturn(pDevIns, VERR_INVALID_HANDLE);
2282 AssertReturn(pDevIns->pDevInsForR3 == pReq->pDevInsR3, VERR_INVALID_HANDLE);
2283
2284 /*
2285 * Make the call.
2286 */
2287 rc = VINF_SUCCESS /*VINF_NOT_IMPLEMENTED*/;
2288 switch (pReq->enmCall)
2289 {
2290 case PDMDEVICEGENCALL_CONSTRUCT:
2291 AssertMsgBreakStmt(pGVM->enmVMState < VMSTATE_CREATED, ("enmVMState=%d\n", pGVM->enmVMState), rc = VERR_INVALID_STATE);
2292 AssertReturn(idCpu == 0, VERR_VM_THREAD_NOT_EMT);
2293 if (pDevIns->pReg->pfnConstruct)
2294 rc = pDevIns->pReg->pfnConstruct(pDevIns);
2295 break;
2296
2297 case PDMDEVICEGENCALL_DESTRUCT:
2298 AssertMsgBreakStmt(pGVM->enmVMState < VMSTATE_CREATED || pGVM->enmVMState >= VMSTATE_DESTROYING,
2299 ("enmVMState=%d\n", pGVM->enmVMState), rc = VERR_INVALID_STATE);
2300 AssertReturn(idCpu == 0, VERR_VM_THREAD_NOT_EMT);
2301 if (pDevIns->pReg->pfnDestruct)
2302 {
2303 pDevIns->pReg->pfnDestruct(pDevIns);
2304 rc = VINF_SUCCESS;
2305 }
2306 break;
2307
2308 case PDMDEVICEGENCALL_REQUEST:
2309 if (pDevIns->pReg->pfnRequest)
2310 rc = pDevIns->pReg->pfnRequest(pDevIns, pReq->Params.Req.uReq, pReq->Params.Req.uArg);
2311 else
2312 rc = VERR_INVALID_FUNCTION;
2313 break;
2314
2315 default:
2316 AssertMsgFailed(("enmCall=%d\n", pReq->enmCall));
2317 rc = VERR_INVALID_FUNCTION;
2318 break;
2319 }
2320
2321 return rc;
2322}
2323
2324
2325/**
2326 * Legacy device mode compatiblity.
2327 *
2328 * @returns VBox status code.
2329 * @param pGVM The global (ring-0) VM structure.
2330 * @param pReq Pointer to the request buffer.
2331 * @thread EMT(0)
2332 */
2333VMMR0_INT_DECL(int) PDMR0DeviceCompatSetCritSectReqHandler(PGVM pGVM, PPDMDEVICECOMPATSETCRITSECTREQ pReq)
2334{
2335 /*
2336 * Validate the request.
2337 */
2338 AssertReturn(pReq->Hdr.cbReq == sizeof(*pReq), VERR_INVALID_PARAMETER);
2339
2340 int rc = GVMMR0ValidateGVMandEMT(pGVM, 0);
2341 AssertRCReturn(rc, rc);
2342
2343 AssertReturn(pReq->idxR0Device < pGVM->pdmr0.s.cDevInstances, VERR_INVALID_HANDLE);
2344 PPDMDEVINSR0 pDevIns = pGVM->pdmr0.s.apDevInstances[pReq->idxR0Device];
2345 AssertPtrReturn(pDevIns, VERR_INVALID_HANDLE);
2346 AssertReturn(pDevIns->pDevInsForR3 == pReq->pDevInsR3, VERR_INVALID_HANDLE);
2347
2348 AssertReturn(pGVM->enmVMState == VMSTATE_CREATING, VERR_INVALID_STATE);
2349
2350 /*
2351 * The critical section address can be in a few different places:
2352 * 1. shared data.
2353 * 2. nop section.
2354 * 3. pdm critsect.
2355 */
2356 PPDMCRITSECT pCritSect;
2357 if (pReq->pCritSectR3 == pGVM->pVMR3 + RT_UOFFSETOF(VM, pdm.s.NopCritSect))
2358 {
2359 pCritSect = &pGVM->pdm.s.NopCritSect;
2360 Log(("PDMR0DeviceCompatSetCritSectReqHandler: Nop - %p %#x\n", pCritSect, pCritSect->s.Core.u32Magic));
2361 }
2362 else if (pReq->pCritSectR3 == pGVM->pVMR3 + RT_UOFFSETOF(VM, pdm.s.CritSect))
2363 {
2364 pCritSect = &pGVM->pdm.s.CritSect;
2365 Log(("PDMR0DeviceCompatSetCritSectReqHandler: PDM - %p %#x\n", pCritSect, pCritSect->s.Core.u32Magic));
2366 }
2367 else
2368 {
2369 size_t offCritSect = pReq->pCritSectR3 - pDevIns->pDevInsForR3R0->pvInstanceDataR3;
2370 AssertLogRelMsgReturn( offCritSect < pDevIns->pReg->cbInstanceShared
2371 && offCritSect + sizeof(PDMCRITSECT) <= pDevIns->pReg->cbInstanceShared,
2372 ("offCritSect=%p pCritSectR3=%p cbInstanceShared=%#x (%s)\n",
2373 offCritSect, pReq->pCritSectR3, pDevIns->pReg->cbInstanceShared, pDevIns->pReg->szName),
2374 VERR_INVALID_POINTER);
2375 pCritSect = (PPDMCRITSECT)((uint8_t *)pDevIns->pvInstanceDataR0 + offCritSect);
2376 Log(("PDMR0DeviceCompatSetCritSectReqHandler: custom - %#x/%p %#x\n", offCritSect, pCritSect, pCritSect->s.Core.u32Magic));
2377 }
2378 AssertLogRelMsgReturn(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC,
2379 ("cs=%p magic=%#x dev=%s\n", pCritSect, pCritSect->s.Core.u32Magic, pDevIns->pReg->szName),
2380 VERR_INVALID_MAGIC);
2381
2382 /*
2383 * Make the update.
2384 */
2385 pDevIns->pCritSectRoR0 = pCritSect;
2386
2387 return VINF_SUCCESS;
2388}
2389
2390
2391/**
2392 * Registers the device implementations living in a module.
2393 *
2394 * This should normally only be called during ModuleInit(). The should be a
2395 * call to PDMR0DeviceDeregisterModule from the ModuleTerm() function to undo
2396 * the effects of this call.
2397 *
2398 * @returns VBox status code.
2399 * @param hMod The module handle of the module being registered.
2400 * @param pModReg The module registration structure. This will be
2401 * used directly so it must live as long as the module
2402 * and be writable.
2403 *
2404 * @note Caller must own the loader lock!
2405 */
2406VMMR0DECL(int) PDMR0DeviceRegisterModule(void *hMod, PPDMDEVMODREGR0 pModReg)
2407{
2408 /*
2409 * Validate the input.
2410 */
2411 AssertPtrReturn(hMod, VERR_INVALID_HANDLE);
2412 Assert(SUPR0LdrIsLockOwnerByMod(hMod, true));
2413
2414 AssertPtrReturn(pModReg, VERR_INVALID_POINTER);
2415 AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE(pModReg->u32Version, PDM_DEVMODREGR0_VERSION),
2416 ("pModReg->u32Version=%#x vs %#x\n", pModReg->u32Version, PDM_DEVMODREGR0_VERSION),
2417 VERR_VERSION_MISMATCH);
2418 AssertLogRelMsgReturn(pModReg->cDevRegs <= 256 && pModReg->cDevRegs > 0, ("cDevRegs=%u\n", pModReg->cDevRegs),
2419 VERR_OUT_OF_RANGE);
2420 AssertLogRelMsgReturn(pModReg->hMod == NULL, ("hMod=%p\n", pModReg->hMod), VERR_INVALID_PARAMETER);
2421 AssertLogRelMsgReturn(pModReg->ListEntry.pNext == NULL, ("pNext=%p\n", pModReg->ListEntry.pNext), VERR_INVALID_PARAMETER);
2422 AssertLogRelMsgReturn(pModReg->ListEntry.pPrev == NULL, ("pPrev=%p\n", pModReg->ListEntry.pPrev), VERR_INVALID_PARAMETER);
2423
2424 for (size_t i = 0; i < pModReg->cDevRegs; i++)
2425 {
2426 PCPDMDEVREGR0 pDevReg = pModReg->papDevRegs[i];
2427 AssertLogRelMsgReturn(RT_VALID_PTR(pDevReg), ("[%u]: %p\n", i, pDevReg), VERR_INVALID_POINTER);
2428 AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE(pDevReg->u32Version, PDM_DEVREGR0_VERSION),
2429 ("pDevReg->u32Version=%#x vs %#x\n", pModReg->u32Version, PDM_DEVREGR0_VERSION), VERR_VERSION_MISMATCH);
2430 AssertLogRelMsgReturn(RT_VALID_PTR(pDevReg->pszDescription), ("[%u]: %p\n", i, pDevReg->pszDescription), VERR_INVALID_POINTER);
2431 AssertLogRelMsgReturn(pDevReg->uReserved0 == 0, ("[%u]: %#x\n", i, pDevReg->uReserved0), VERR_INVALID_PARAMETER);
2432 AssertLogRelMsgReturn(pDevReg->fClass != 0, ("[%u]: %#x\n", i, pDevReg->fClass), VERR_INVALID_PARAMETER);
2433 AssertLogRelMsgReturn(pDevReg->fFlags != 0, ("[%u]: %#x\n", i, pDevReg->fFlags), VERR_INVALID_PARAMETER);
2434 AssertLogRelMsgReturn(pDevReg->cMaxInstances > 0, ("[%u]: %#x\n", i, pDevReg->cMaxInstances), VERR_INVALID_PARAMETER);
2435 AssertLogRelMsgReturn(pDevReg->cMaxPciDevices <= 8, ("[%u]: %#x\n", i, pDevReg->cMaxPciDevices), VERR_INVALID_PARAMETER);
2436 AssertLogRelMsgReturn(pDevReg->cMaxMsixVectors <= VBOX_MSIX_MAX_ENTRIES,
2437 ("[%u]: %#x\n", i, pDevReg->cMaxMsixVectors), VERR_INVALID_PARAMETER);
2438
2439 /* The name must be printable ascii and correctly terminated. */
2440 for (size_t off = 0; off < RT_ELEMENTS(pDevReg->szName); off++)
2441 {
2442 char ch = pDevReg->szName[off];
2443 AssertLogRelMsgReturn(RT_C_IS_PRINT(ch) || (ch == '\0' && off > 0),
2444 ("[%u]: off=%u szName: %.*Rhxs\n", i, off, sizeof(pDevReg->szName), &pDevReg->szName[0]),
2445 VERR_INVALID_NAME);
2446 if (ch == '\0')
2447 break;
2448 }
2449 }
2450
2451 /*
2452 * Add it, assuming we're being called at ModuleInit/ModuleTerm time only, or
2453 * that the caller has already taken the loader lock.
2454 */
2455 pModReg->hMod = hMod;
2456 RTListAppend(&g_PDMDevModList, &pModReg->ListEntry);
2457
2458 return VINF_SUCCESS;
2459}
2460
2461
2462/**
2463 * Deregisters the device implementations living in a module.
2464 *
2465 * This should normally only be called during ModuleTerm().
2466 *
2467 * @returns VBox status code.
2468 * @param hMod The module handle of the module being registered.
2469 * @param pModReg The module registration structure. This will be
2470 * used directly so it must live as long as the module
2471 * and be writable.
2472 *
2473 * @note Caller must own the loader lock!
2474 */
2475VMMR0DECL(int) PDMR0DeviceDeregisterModule(void *hMod, PPDMDEVMODREGR0 pModReg)
2476{
2477 /*
2478 * Validate the input.
2479 */
2480 AssertPtrReturn(hMod, VERR_INVALID_HANDLE);
2481 Assert(SUPR0LdrIsLockOwnerByMod(hMod, true));
2482
2483 AssertPtrReturn(pModReg, VERR_INVALID_POINTER);
2484 AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE(pModReg->u32Version, PDM_DEVMODREGR0_VERSION),
2485 ("pModReg->u32Version=%#x vs %#x\n", pModReg->u32Version, PDM_DEVMODREGR0_VERSION),
2486 VERR_VERSION_MISMATCH);
2487 AssertLogRelMsgReturn(pModReg->hMod == hMod || pModReg->hMod == NULL, ("pModReg->hMod=%p vs %p\n", pModReg->hMod, hMod),
2488 VERR_INVALID_PARAMETER);
2489
2490 /*
2491 * Unlink the registration record and return it to virgin conditions. Ignore
2492 * the call if not registered.
2493 */
2494 if (pModReg->hMod)
2495 {
2496 pModReg->hMod = NULL;
2497 RTListNodeRemove(&pModReg->ListEntry);
2498 pModReg->ListEntry.pNext = NULL;
2499 pModReg->ListEntry.pPrev = NULL;
2500 return VINF_SUCCESS;
2501 }
2502 return VWRN_NOT_FOUND;
2503}
2504
Note: See TracBrowser for help on using the repository browser.

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