VirtualBox

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

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

PDM,DevACPI,DevHPET,DevPit-i8254,DevRTC,APIC: Added device helpers for locking and unlocking both the virtual-sync clock and entering a user specified critical section. bugref:9218

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

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