VirtualBox

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

Last change on this file since 64596 was 64596, checked in by vboxsync, 9 years ago

VMM/APIC, PDM: Clean up PDM APIC helper interface, call VMM directly instead.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 29.7 KB
Line 
1/* $Id: PDMR0Device.cpp 64596 2016-11-08 15:03:18Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, R0 Device parts.
4 */
5
6/*
7 * Copyright (C) 2006-2016 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/pgm.h>
27#include <VBox/vmm/mm.h>
28#include <VBox/vmm/vm.h>
29#include <VBox/vmm/vmm.h>
30#include <VBox/vmm/patm.h>
31#include <VBox/vmm/hm.h>
32
33#include <VBox/log.h>
34#include <VBox/err.h>
35#include <VBox/vmm/gvmm.h>
36#include <iprt/asm.h>
37#include <iprt/assert.h>
38#include <iprt/string.h>
39
40#include "dtrace/VBoxVMM.h"
41#include "PDMInline.h"
42
43
44/*********************************************************************************************************************************
45* Global Variables *
46*********************************************************************************************************************************/
47RT_C_DECLS_BEGIN
48extern DECLEXPORT(const PDMDEVHLPR0) g_pdmR0DevHlp;
49extern DECLEXPORT(const PDMPICHLPR0) g_pdmR0PicHlp;
50extern DECLEXPORT(const PDMIOAPICHLPR0) g_pdmR0IoApicHlp;
51extern DECLEXPORT(const PDMPCIHLPR0) g_pdmR0PciHlp;
52extern DECLEXPORT(const PDMHPETHLPR0) g_pdmR0HpetHlp;
53extern DECLEXPORT(const PDMPCIRAWHLPR0) g_pdmR0PciRawHlp;
54extern DECLEXPORT(const PDMDRVHLPR0) g_pdmR0DrvHlp;
55RT_C_DECLS_END
56
57
58/*********************************************************************************************************************************
59* Internal Functions *
60*********************************************************************************************************************************/
61static bool pdmR0IsaSetIrq(PVM pVM, int iIrq, int iLevel, uint32_t uTagSrc);
62
63
64
65/** @name Ring-0 Device Helpers
66 * @{
67 */
68
69/** @interface_method_impl{PDMDEVHLPR0,pfnPCIPhysRead} */
70static DECLCALLBACK(int) pdmR0DevHlp_PCIPhysRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
71 void *pvBuf, size_t cbRead)
72{
73 PDMDEV_ASSERT_DEVINS(pDevIns);
74 if (!pPciDev) /* NULL is an alias for the default PCI device. */
75 pPciDev = pDevIns->Internal.s.pHeadPciDevR0;
76 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
77
78#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
79 /*
80 * Just check the busmaster setting here and forward the request to the generic read helper.
81 */
82 if (PCIDevIsBusmaster(pPciDev))
83 { /* likely */ }
84 else
85 {
86 Log(("pdmRCDevHlp_PCIPhysRead: caller=%p/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbRead=%#zx\n",
87 pDevIns, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbRead));
88 return VERR_PDM_NOT_PCI_BUS_MASTER;
89 }
90#endif
91
92 return pDevIns->pHlpR0->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead);
93}
94
95
96/** @interface_method_impl{PDMDEVHLPR0,pfnPCIPhysWrite} */
97static DECLCALLBACK(int) pdmR0DevHlp_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
98 const void *pvBuf, size_t cbWrite)
99{
100 PDMDEV_ASSERT_DEVINS(pDevIns);
101 if (!pPciDev) /* NULL is an alias for the default PCI device. */
102 pPciDev = pDevIns->Internal.s.pHeadPciDevR0;
103 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
104
105#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
106 /*
107 * Just check the busmaster setting here and forward the request to the generic read helper.
108 */
109 if (PCIDevIsBusmaster(pPciDev))
110 { /* likely */ }
111 else
112 {
113 Log(("pdmRCDevHlp_PCIPhysWrite: caller=%p/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n",
114 pDevIns, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
115 return VERR_PDM_NOT_PCI_BUS_MASTER;
116 }
117#endif
118
119 return pDevIns->pHlpR0->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite);
120}
121
122
123/** @interface_method_impl{PDMDEVHLPR0,pfnPCISetIrq} */
124static DECLCALLBACK(void) pdmR0DevHlp_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
125{
126 PDMDEV_ASSERT_DEVINS(pDevIns);
127 if (!pPciDev) /* NULL is an alias for the default PCI device. */
128 pPciDev = pDevIns->Internal.s.pHeadPciDevR0;
129 AssertReturnVoid(pPciDev);
130 LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
131 pDevIns, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
132 PVM pVM = pDevIns->Internal.s.pVMR0;
133 PPDMPCIBUS pPciBus = pPciDev->Int.s.pPdmBusR0;
134
135 pdmLock(pVM);
136 uint32_t uTagSrc;
137 if (iLevel & PDM_IRQ_LEVEL_HIGH)
138 {
139 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
140 if (iLevel == PDM_IRQ_LEVEL_HIGH)
141 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
142 else
143 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
144 }
145 else
146 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
147
148 if ( pPciBus
149 && pPciBus->pDevInsR0)
150 {
151 pPciBus->pfnSetIrqR0(pPciBus->pDevInsR0, pPciDev, iIrq, iLevel, uTagSrc);
152
153 pdmUnlock(pVM);
154
155 if (iLevel == PDM_IRQ_LEVEL_LOW)
156 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
157 }
158 else
159 {
160 pdmUnlock(pVM);
161
162 /* queue for ring-3 execution. */
163 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueR0);
164 AssertReturnVoid(pTask);
165
166 pTask->enmOp = PDMDEVHLPTASKOP_PCI_SET_IRQ;
167 pTask->pDevInsR3 = PDMDEVINS_2_R3PTR(pDevIns);
168 pTask->u.PciSetIRQ.iIrq = iIrq;
169 pTask->u.PciSetIRQ.iLevel = iLevel;
170 pTask->u.PciSetIRQ.uTagSrc = uTagSrc;
171 pTask->u.PciSetIRQ.pPciDevR3 = MMHyperR0ToR3(pVM, pPciDev);
172
173 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
174 }
175
176 LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, uTagSrc));
177}
178
179
180/** @interface_method_impl{PDMDEVHLPR0,pfnISASetIrq} */
181static DECLCALLBACK(void) pdmR0DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
182{
183 PDMDEV_ASSERT_DEVINS(pDevIns);
184 LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
185 PVM pVM = pDevIns->Internal.s.pVMR0;
186
187 pdmLock(pVM);
188 uint32_t uTagSrc;
189 if (iLevel & PDM_IRQ_LEVEL_HIGH)
190 {
191 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
192 if (iLevel == PDM_IRQ_LEVEL_HIGH)
193 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
194 else
195 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
196 }
197 else
198 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
199
200 bool fRc = pdmR0IsaSetIrq(pVM, iIrq, iLevel, uTagSrc);
201
202 if (iLevel == PDM_IRQ_LEVEL_LOW && fRc)
203 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
204 pdmUnlock(pVM);
205 LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, uTagSrc));
206}
207
208
209/** @interface_method_impl{PDMDEVHLPR0,pfnPhysRead} */
210static DECLCALLBACK(int) pdmR0DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
211{
212 PDMDEV_ASSERT_DEVINS(pDevIns);
213 LogFlow(("pdmR0DevHlp_PhysRead: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
214 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
215
216 VBOXSTRICTRC rcStrict = PGMPhysRead(pDevIns->Internal.s.pVMR0, GCPhys, pvBuf, cbRead, PGMACCESSORIGIN_DEVICE);
217 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
218
219 Log(("pdmR0DevHlp_PhysRead: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
220 return VBOXSTRICTRC_VAL(rcStrict);
221}
222
223
224/** @interface_method_impl{PDMDEVHLPR0,pfnPhysWrite} */
225static DECLCALLBACK(int) pdmR0DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
226{
227 PDMDEV_ASSERT_DEVINS(pDevIns);
228 LogFlow(("pdmR0DevHlp_PhysWrite: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
229 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
230
231 VBOXSTRICTRC rcStrict = PGMPhysWrite(pDevIns->Internal.s.pVMR0, GCPhys, pvBuf, cbWrite, PGMACCESSORIGIN_DEVICE);
232 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
233
234 Log(("pdmR0DevHlp_PhysWrite: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
235 return VBOXSTRICTRC_VAL(rcStrict);
236}
237
238
239/** @interface_method_impl{PDMDEVHLPR0,pfnA20IsEnabled} */
240static DECLCALLBACK(bool) pdmR0DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
241{
242 PDMDEV_ASSERT_DEVINS(pDevIns);
243 LogFlow(("pdmR0DevHlp_A20IsEnabled: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
244
245 bool fEnabled = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pVMR0));
246
247 Log(("pdmR0DevHlp_A20IsEnabled: caller=%p/%d: returns %RTbool\n", pDevIns, pDevIns->iInstance, fEnabled));
248 return fEnabled;
249}
250
251
252/** @interface_method_impl{PDMDEVHLPR0,pfnVMState} */
253static DECLCALLBACK(VMSTATE) pdmR0DevHlp_VMState(PPDMDEVINS pDevIns)
254{
255 PDMDEV_ASSERT_DEVINS(pDevIns);
256
257 VMSTATE enmVMState = pDevIns->Internal.s.pVMR0->enmVMState;
258
259 LogFlow(("pdmR0DevHlp_VMState: caller=%p/%d: returns %d\n", pDevIns, pDevIns->iInstance, enmVMState));
260 return enmVMState;
261}
262
263
264/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetError} */
265static DECLCALLBACK(int) pdmR0DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
266{
267 PDMDEV_ASSERT_DEVINS(pDevIns);
268 va_list args;
269 va_start(args, pszFormat);
270 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR0, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
271 va_end(args);
272 return rc;
273}
274
275
276/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetErrorV} */
277static DECLCALLBACK(int) pdmR0DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
278{
279 PDMDEV_ASSERT_DEVINS(pDevIns);
280 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR0, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
281 return rc;
282}
283
284
285/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetRuntimeError} */
286static DECLCALLBACK(int) pdmR0DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
287{
288 PDMDEV_ASSERT_DEVINS(pDevIns);
289 va_list va;
290 va_start(va, pszFormat);
291 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR0, fFlags, pszErrorId, pszFormat, va);
292 va_end(va);
293 return rc;
294}
295
296
297/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetRuntimeErrorV} */
298static DECLCALLBACK(int) pdmR0DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
299{
300 PDMDEV_ASSERT_DEVINS(pDevIns);
301 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR0, fFlags, pszErrorId, pszFormat, va);
302 return rc;
303}
304
305
306/** @interface_method_impl{PDMDEVHLPR0,pfnPATMSetMMIOPatchInfo} */
307static DECLCALLBACK(int) pdmR0DevHlp_PATMSetMMIOPatchInfo(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPTR pCachedData)
308{
309 PDMDEV_ASSERT_DEVINS(pDevIns);
310 LogFlow(("pdmR0DevHlp_PATMSetMMIOPatchInfo: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
311
312 AssertFailed();
313 NOREF(GCPhys); NOREF(pCachedData); NOREF(pDevIns);
314
315/* return PATMSetMMIOPatchInfo(pDevIns->Internal.s.pVMR0, GCPhys, pCachedData); */
316 return VINF_SUCCESS;
317}
318
319
320/** @interface_method_impl{PDMDEVHLPR0,pfnGetVM} */
321static DECLCALLBACK(PVM) pdmR0DevHlp_GetVM(PPDMDEVINS pDevIns)
322{
323 PDMDEV_ASSERT_DEVINS(pDevIns);
324 LogFlow(("pdmR0DevHlp_GetVM: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
325 return pDevIns->Internal.s.pVMR0;
326}
327
328
329/** @interface_method_impl{PDMDEVHLPR0,pfnGetVMCPU} */
330static DECLCALLBACK(PVMCPU) pdmR0DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
331{
332 PDMDEV_ASSERT_DEVINS(pDevIns);
333 LogFlow(("pdmR0DevHlp_GetVMCPU: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
334 return VMMGetCpu(pDevIns->Internal.s.pVMR0);
335}
336
337
338/** @interface_method_impl{PDMDEVHLPRC,pfnGetCurrentCpuId} */
339static DECLCALLBACK(VMCPUID) pdmR0DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
340{
341 PDMDEV_ASSERT_DEVINS(pDevIns);
342 VMCPUID idCpu = VMMGetCpuId(pDevIns->Internal.s.pVMR0);
343 LogFlow(("pdmR0DevHlp_GetCurrentCpuId: caller='%p'/%d for CPU %u\n", pDevIns, pDevIns->iInstance, idCpu));
344 return idCpu;
345}
346
347
348/** @interface_method_impl{PDMDEVHLPR0,pfnTMTimeVirtGet} */
349static DECLCALLBACK(uint64_t) pdmR0DevHlp_TMTimeVirtGet(PPDMDEVINS pDevIns)
350{
351 PDMDEV_ASSERT_DEVINS(pDevIns);
352 LogFlow(("pdmR0DevHlp_TMTimeVirtGet: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
353 return TMVirtualGet(pDevIns->Internal.s.pVMR0);
354}
355
356
357/** @interface_method_impl{PDMDEVHLPR0,pfnTMTimeVirtGetFreq} */
358static DECLCALLBACK(uint64_t) pdmR0DevHlp_TMTimeVirtGetFreq(PPDMDEVINS pDevIns)
359{
360 PDMDEV_ASSERT_DEVINS(pDevIns);
361 LogFlow(("pdmR0DevHlp_TMTimeVirtGetFreq: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
362 return TMVirtualGetFreq(pDevIns->Internal.s.pVMR0);
363}
364
365
366/** @interface_method_impl{PDMDEVHLPR0,pfnTMTimeVirtGetNano} */
367static DECLCALLBACK(uint64_t) pdmR0DevHlp_TMTimeVirtGetNano(PPDMDEVINS pDevIns)
368{
369 PDMDEV_ASSERT_DEVINS(pDevIns);
370 LogFlow(("pdmR0DevHlp_TMTimeVirtGetNano: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
371 return TMVirtualToNano(pDevIns->Internal.s.pVMR0, TMVirtualGet(pDevIns->Internal.s.pVMR0));
372}
373
374
375/** @interface_method_impl{PDMDEVHLPR0,pfnDBGFTraceBuf} */
376static DECLCALLBACK(RTTRACEBUF) pdmR0DevHlp_DBGFTraceBuf(PPDMDEVINS pDevIns)
377{
378 PDMDEV_ASSERT_DEVINS(pDevIns);
379 RTTRACEBUF hTraceBuf = pDevIns->Internal.s.pVMR0->hTraceBufR0;
380 LogFlow(("pdmR3DevHlp_DBGFTraceBuf: caller='%p'/%d: returns %p\n", pDevIns, pDevIns->iInstance, hTraceBuf));
381 return hTraceBuf;
382}
383
384
385/** @interface_method_impl{PDMDEVHLPR0,pfnCanEmulateIoBlock} */
386static DECLCALLBACK(bool) pdmR0DevHlp_CanEmulateIoBlock(PPDMDEVINS pDevIns)
387{
388 PDMDEV_ASSERT_DEVINS(pDevIns);
389 LogFlow(("pdmR0DevHlp_GetVM: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
390 return HMCanEmulateIoBlock(VMMGetCpu(pDevIns->Internal.s.pVMR0));
391}
392
393
394/**
395 * The Ring-0 Device Helper Callbacks.
396 */
397extern DECLEXPORT(const PDMDEVHLPR0) g_pdmR0DevHlp =
398{
399 PDM_DEVHLPR0_VERSION,
400 pdmR0DevHlp_PCIPhysRead,
401 pdmR0DevHlp_PCIPhysWrite,
402 pdmR0DevHlp_PCISetIrq,
403 pdmR0DevHlp_ISASetIrq,
404 pdmR0DevHlp_PhysRead,
405 pdmR0DevHlp_PhysWrite,
406 pdmR0DevHlp_A20IsEnabled,
407 pdmR0DevHlp_VMState,
408 pdmR0DevHlp_VMSetError,
409 pdmR0DevHlp_VMSetErrorV,
410 pdmR0DevHlp_VMSetRuntimeError,
411 pdmR0DevHlp_VMSetRuntimeErrorV,
412 pdmR0DevHlp_PATMSetMMIOPatchInfo,
413 pdmR0DevHlp_GetVM,
414 pdmR0DevHlp_CanEmulateIoBlock,
415 pdmR0DevHlp_GetVMCPU,
416 pdmR0DevHlp_GetCurrentCpuId,
417 pdmR0DevHlp_TMTimeVirtGet,
418 pdmR0DevHlp_TMTimeVirtGetFreq,
419 pdmR0DevHlp_TMTimeVirtGetNano,
420 pdmR0DevHlp_DBGFTraceBuf,
421 NULL,
422 NULL,
423 NULL,
424 NULL,
425 NULL,
426 NULL,
427 NULL,
428 NULL,
429 NULL,
430 NULL,
431 PDM_DEVHLPR0_VERSION
432};
433
434/** @} */
435
436
437
438
439/** @name PIC Ring-0 Helpers
440 * @{
441 */
442
443/** @interface_method_impl{PDMPICHLPR0,pfnSetInterruptFF} */
444static DECLCALLBACK(void) pdmR0PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
445{
446 PDMDEV_ASSERT_DEVINS(pDevIns);
447 PVM pVM = pDevIns->Internal.s.pVMR0;
448 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
449
450 if (pVM->pdm.s.Apic.pfnLocalInterruptR0)
451 {
452 LogFlow(("pdmR0PicHlp_SetInterruptFF: caller='%p'/%d: Setting local interrupt on LAPIC\n",
453 pDevIns, pDevIns->iInstance));
454 /* Raise the LAPIC's LINT0 line instead of signaling the CPU directly. */
455 /** @todo rcRZ propagation to pfnLocalInterrupt from caller. */
456 pVM->pdm.s.Apic.pfnLocalInterruptR0(pVM->pdm.s.Apic.pDevInsR0, pVCpu, 0 /* u8Pin */, 1 /* u8Level */,
457 VINF_SUCCESS /* rcRZ */);
458 return;
459 }
460
461 LogFlow(("pdmR0PicHlp_SetInterruptFF: caller=%p/%d: VMCPU_FF_INTERRUPT_PIC %d -> 1\n",
462 pDevIns, pDevIns->iInstance, VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC)));
463
464 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC);
465}
466
467
468/** @interface_method_impl{PDMPICHLPR0,pfnClearInterruptFF} */
469static DECLCALLBACK(void) pdmR0PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
470{
471 PDMDEV_ASSERT_DEVINS(pDevIns);
472 PVM pVM = pDevIns->Internal.s.pVMR0;
473 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
474
475 if (pVM->pdm.s.Apic.pfnLocalInterruptR0)
476 {
477 /* Raise the LAPIC's LINT0 line instead of signaling the CPU directly. */
478 LogFlow(("pdmR0PicHlp_ClearInterruptFF: caller='%s'/%d: Clearing local interrupt on LAPIC\n",
479 pDevIns, pDevIns->iInstance));
480 /* Lower the LAPIC's LINT0 line instead of signaling the CPU directly. */
481 /** @todo rcRZ propagation to pfnLocalInterrupt from caller. */
482 pVM->pdm.s.Apic.pfnLocalInterruptR0(pVM->pdm.s.Apic.pDevInsR0, pVCpu, 0 /* u8Pin */, 0 /* u8Level */,
483 VINF_SUCCESS /* rcRZ */);
484 return;
485 }
486
487 LogFlow(("pdmR0PicHlp_ClearInterruptFF: caller=%p/%d: VMCPU_FF_INTERRUPT_PIC %d -> 0\n",
488 pDevIns, pDevIns->iInstance, VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC)));
489
490 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
491}
492
493
494/** @interface_method_impl{PDMPICHLPR0,pfnLock} */
495static DECLCALLBACK(int) pdmR0PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
496{
497 PDMDEV_ASSERT_DEVINS(pDevIns);
498 return pdmLockEx(pDevIns->Internal.s.pVMR0, rc);
499}
500
501
502/** @interface_method_impl{PDMPICHLPR0,pfnUnlock} */
503static DECLCALLBACK(void) pdmR0PicHlp_Unlock(PPDMDEVINS pDevIns)
504{
505 PDMDEV_ASSERT_DEVINS(pDevIns);
506 pdmUnlock(pDevIns->Internal.s.pVMR0);
507}
508
509
510/**
511 * The Ring-0 PIC Helper Callbacks.
512 */
513extern DECLEXPORT(const PDMPICHLPR0) g_pdmR0PicHlp =
514{
515 PDM_PICHLPR0_VERSION,
516 pdmR0PicHlp_SetInterruptFF,
517 pdmR0PicHlp_ClearInterruptFF,
518 pdmR0PicHlp_Lock,
519 pdmR0PicHlp_Unlock,
520 PDM_PICHLPR0_VERSION
521};
522
523/** @} */
524
525
526/** @name I/O APIC Ring-0 Helpers
527 * @{
528 */
529
530/** @interface_method_impl{PDMIOAPICHLPR0,pfnApicBusDeliver} */
531static DECLCALLBACK(int) pdmR0IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
532 uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc)
533{
534 PDMDEV_ASSERT_DEVINS(pDevIns);
535 PVM pVM = pDevIns->Internal.s.pVMR0;
536 LogFlow(("pdmR0IoApicHlp_ApicBusDeliver: caller=%p/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8 uTagSrc=%#x\n",
537 pDevIns, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode, uTagSrc));
538 Assert(pVM->pdm.s.Apic.pDevInsR0);
539 if (pVM->pdm.s.Apic.pfnBusDeliverR0)
540 return pVM->pdm.s.Apic.pfnBusDeliverR0(pVM->pdm.s.Apic.pDevInsR0, u8Dest, u8DestMode, u8DeliveryMode, iVector,
541 u8Polarity, u8TriggerMode, uTagSrc);
542 return VINF_SUCCESS;
543}
544
545
546/** @interface_method_impl{PDMIOAPICHLPR0,pfnLock} */
547static DECLCALLBACK(int) pdmR0IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
548{
549 PDMDEV_ASSERT_DEVINS(pDevIns);
550 return pdmLockEx(pDevIns->Internal.s.pVMR0, rc);
551}
552
553
554/** @interface_method_impl{PDMIOAPICHLPR0,pfnUnlock} */
555static DECLCALLBACK(void) pdmR0IoApicHlp_Unlock(PPDMDEVINS pDevIns)
556{
557 PDMDEV_ASSERT_DEVINS(pDevIns);
558 pdmUnlock(pDevIns->Internal.s.pVMR0);
559}
560
561
562/**
563 * The Ring-0 I/O APIC Helper Callbacks.
564 */
565extern DECLEXPORT(const PDMIOAPICHLPR0) g_pdmR0IoApicHlp =
566{
567 PDM_IOAPICHLPR0_VERSION,
568 pdmR0IoApicHlp_ApicBusDeliver,
569 pdmR0IoApicHlp_Lock,
570 pdmR0IoApicHlp_Unlock,
571 PDM_IOAPICHLPR0_VERSION
572};
573
574/** @} */
575
576
577
578
579/** @name PCI Bus Ring-0 Helpers
580 * @{
581 */
582
583/** @interface_method_impl{PDMPCIHLPR0,pfnIsaSetIrq} */
584static DECLCALLBACK(void) pdmR0PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
585{
586 PDMDEV_ASSERT_DEVINS(pDevIns);
587 Log4(("pdmR0PciHlp_IsaSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
588 PVM pVM = pDevIns->Internal.s.pVMR0;
589
590 pdmLock(pVM);
591 pdmR0IsaSetIrq(pVM, iIrq, iLevel, uTagSrc);
592 pdmUnlock(pVM);
593}
594
595
596/** @interface_method_impl{PDMPCIHLPR0,pfnIoApicSetIrq} */
597static DECLCALLBACK(void) pdmR0PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
598{
599 PDMDEV_ASSERT_DEVINS(pDevIns);
600 Log4(("pdmR0PciHlp_IoApicSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
601 PVM pVM = pDevIns->Internal.s.pVMR0;
602
603 if (pVM->pdm.s.IoApic.pDevInsR0)
604 {
605#ifdef VBOX_WITH_NEW_IOAPIC
606 pVM->pdm.s.IoApic.pfnSetIrqR0(pVM->pdm.s.IoApic.pDevInsR0, iIrq, iLevel, uTagSrc);
607#else
608 pdmLock(pVM);
609 pVM->pdm.s.IoApic.pfnSetIrqR0(pVM->pdm.s.IoApic.pDevInsR0, iIrq, iLevel, uTagSrc);
610 pdmUnlock(pVM);
611#endif
612 }
613 else if (pVM->pdm.s.IoApic.pDevInsR3)
614 {
615 /* queue for ring-3 execution. */
616 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueR0);
617 if (pTask)
618 {
619 pTask->enmOp = PDMDEVHLPTASKOP_IOAPIC_SET_IRQ;
620 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
621 pTask->u.IoApicSetIRQ.iIrq = iIrq;
622 pTask->u.IoApicSetIRQ.iLevel = iLevel;
623 pTask->u.IoApicSetIRQ.uTagSrc = uTagSrc;
624
625 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
626 }
627 else
628 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
629 }
630}
631
632
633/** @interface_method_impl{PDMPCIHLPR0,pfnIoApicSendMsi} */
634static DECLCALLBACK(void) pdmR0PciHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc)
635{
636 PDMDEV_ASSERT_DEVINS(pDevIns);
637 Log4(("pdmR0PciHlp_IoApicSendMsi: GCPhys=%p uValue=%d uTagSrc=%#x\n", GCPhys, uValue, uTagSrc));
638 PVM pVM = pDevIns->Internal.s.pVMR0;
639 if (pVM->pdm.s.IoApic.pDevInsR0)
640 {
641#ifdef VBOX_WITH_NEW_IOAPIC
642 pVM->pdm.s.IoApic.pfnSendMsiR0(pVM->pdm.s.IoApic.pDevInsR0, GCPhys, uValue, uTagSrc);
643#else
644 pdmLock(pVM);
645 pVM->pdm.s.IoApic.pfnSendMsiR0(pVM->pdm.s.IoApic.pDevInsR0, GCPhys, uValue, uTagSrc);
646 pdmUnlock(pVM);
647#endif
648 }
649 else
650 AssertFatalMsgFailed(("Lazy bastards!"));
651}
652
653
654/** @interface_method_impl{PDMPCIHLPR0,pfnLock} */
655static DECLCALLBACK(int) pdmR0PciHlp_Lock(PPDMDEVINS pDevIns, int rc)
656{
657 PDMDEV_ASSERT_DEVINS(pDevIns);
658 return pdmLockEx(pDevIns->Internal.s.pVMR0, rc);
659}
660
661
662/** @interface_method_impl{PDMPCIHLPR0,pfnUnlock} */
663static DECLCALLBACK(void) pdmR0PciHlp_Unlock(PPDMDEVINS pDevIns)
664{
665 PDMDEV_ASSERT_DEVINS(pDevIns);
666 pdmUnlock(pDevIns->Internal.s.pVMR0);
667}
668
669
670/**
671 * The Ring-0 PCI Bus Helper Callbacks.
672 */
673extern DECLEXPORT(const PDMPCIHLPR0) g_pdmR0PciHlp =
674{
675 PDM_PCIHLPR0_VERSION,
676 pdmR0PciHlp_IsaSetIrq,
677 pdmR0PciHlp_IoApicSetIrq,
678 pdmR0PciHlp_IoApicSendMsi,
679 pdmR0PciHlp_Lock,
680 pdmR0PciHlp_Unlock,
681 PDM_PCIHLPR0_VERSION, /* the end */
682};
683
684/** @} */
685
686
687
688
689/** @name HPET Ring-0 Helpers
690 * @{
691 */
692/* none */
693
694/**
695 * The Ring-0 HPET Helper Callbacks.
696 */
697extern DECLEXPORT(const PDMHPETHLPR0) g_pdmR0HpetHlp =
698{
699 PDM_HPETHLPR0_VERSION,
700 PDM_HPETHLPR0_VERSION, /* the end */
701};
702
703/** @} */
704
705
706/** @name Raw PCI Ring-0 Helpers
707 * @{
708 */
709/* none */
710
711/**
712 * The Ring-0 PCI raw Helper Callbacks.
713 */
714extern DECLEXPORT(const PDMPCIRAWHLPR0) g_pdmR0PciRawHlp =
715{
716 PDM_PCIRAWHLPR0_VERSION,
717 PDM_PCIRAWHLPR0_VERSION, /* the end */
718};
719
720/** @} */
721
722
723/** @name Ring-0 Context Driver Helpers
724 * @{
725 */
726
727/** @interface_method_impl{PDMDRVHLPR0,pfnVMSetError} */
728static DECLCALLBACK(int) pdmR0DrvHlp_VMSetError(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
729{
730 PDMDRV_ASSERT_DRVINS(pDrvIns);
731 va_list args;
732 va_start(args, pszFormat);
733 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMR0, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
734 va_end(args);
735 return rc;
736}
737
738
739/** @interface_method_impl{PDMDRVHLPR0,pfnVMSetErrorV} */
740static DECLCALLBACK(int) pdmR0DrvHlp_VMSetErrorV(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
741{
742 PDMDRV_ASSERT_DRVINS(pDrvIns);
743 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMR0, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
744 return rc;
745}
746
747
748/** @interface_method_impl{PDMDRVHLPR0,pfnVMSetRuntimeError} */
749static DECLCALLBACK(int) pdmR0DrvHlp_VMSetRuntimeError(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId,
750 const char *pszFormat, ...)
751{
752 PDMDRV_ASSERT_DRVINS(pDrvIns);
753 va_list va;
754 va_start(va, pszFormat);
755 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMR0, fFlags, pszErrorId, pszFormat, va);
756 va_end(va);
757 return rc;
758}
759
760
761/** @interface_method_impl{PDMDRVHLPR0,pfnVMSetRuntimeErrorV} */
762static DECLCALLBACK(int) pdmR0DrvHlp_VMSetRuntimeErrorV(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId,
763 const char *pszFormat, va_list va)
764{
765 PDMDRV_ASSERT_DRVINS(pDrvIns);
766 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMR0, fFlags, pszErrorId, pszFormat, va);
767 return rc;
768}
769
770
771/** @interface_method_impl{PDMDRVHLPR0,pfnAssertEMT} */
772static DECLCALLBACK(bool) pdmR0DrvHlp_AssertEMT(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
773{
774 PDMDRV_ASSERT_DRVINS(pDrvIns);
775 if (VM_IS_EMT(pDrvIns->Internal.s.pVMR0))
776 return true;
777
778 RTAssertMsg1Weak("AssertEMT", iLine, pszFile, pszFunction);
779 RTAssertPanic();
780 return false;
781}
782
783
784/** @interface_method_impl{PDMDRVHLPR0,pfnAssertOther} */
785static DECLCALLBACK(bool) pdmR0DrvHlp_AssertOther(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
786{
787 PDMDRV_ASSERT_DRVINS(pDrvIns);
788 if (!VM_IS_EMT(pDrvIns->Internal.s.pVMR0))
789 return true;
790
791 RTAssertMsg1Weak("AssertOther", iLine, pszFile, pszFunction);
792 RTAssertPanic();
793 return false;
794}
795
796
797/** @interface_method_impl{PDMDRVHLPR0,pfnFTSetCheckpoint} */
798static DECLCALLBACK(int) pdmR0DrvHlp_FTSetCheckpoint(PPDMDRVINS pDrvIns, FTMCHECKPOINTTYPE enmType)
799{
800 PDMDRV_ASSERT_DRVINS(pDrvIns);
801 return FTMSetCheckpoint(pDrvIns->Internal.s.pVMR0, enmType);
802}
803
804
805/**
806 * The Ring-0 Context Driver Helper Callbacks.
807 */
808extern DECLEXPORT(const PDMDRVHLPR0) g_pdmR0DrvHlp =
809{
810 PDM_DRVHLPRC_VERSION,
811 pdmR0DrvHlp_VMSetError,
812 pdmR0DrvHlp_VMSetErrorV,
813 pdmR0DrvHlp_VMSetRuntimeError,
814 pdmR0DrvHlp_VMSetRuntimeErrorV,
815 pdmR0DrvHlp_AssertEMT,
816 pdmR0DrvHlp_AssertOther,
817 pdmR0DrvHlp_FTSetCheckpoint,
818 PDM_DRVHLPRC_VERSION
819};
820
821/** @} */
822
823
824
825
826/**
827 * Sets an irq on the PIC and I/O APIC.
828 *
829 * @returns true if delivered, false if postponed.
830 * @param pVM The cross context VM structure.
831 * @param iIrq The irq.
832 * @param iLevel The new level.
833 * @param uTagSrc The IRQ tag and source.
834 *
835 * @remarks The caller holds the PDM lock.
836 */
837static bool pdmR0IsaSetIrq(PVM pVM, int iIrq, int iLevel, uint32_t uTagSrc)
838{
839 if (RT_LIKELY( ( pVM->pdm.s.IoApic.pDevInsR0
840 || !pVM->pdm.s.IoApic.pDevInsR3)
841 && ( pVM->pdm.s.Pic.pDevInsR0
842 || !pVM->pdm.s.Pic.pDevInsR3)))
843 {
844 if (pVM->pdm.s.Pic.pDevInsR0)
845 pVM->pdm.s.Pic.pfnSetIrqR0(pVM->pdm.s.Pic.pDevInsR0, iIrq, iLevel, uTagSrc);
846 if (pVM->pdm.s.IoApic.pDevInsR0)
847 pVM->pdm.s.IoApic.pfnSetIrqR0(pVM->pdm.s.IoApic.pDevInsR0, iIrq, iLevel, uTagSrc);
848 return true;
849 }
850
851 /* queue for ring-3 execution. */
852 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueR0);
853 AssertReturn(pTask, false);
854
855 pTask->enmOp = PDMDEVHLPTASKOP_ISA_SET_IRQ;
856 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
857 pTask->u.IsaSetIRQ.iIrq = iIrq;
858 pTask->u.IsaSetIRQ.iLevel = iLevel;
859 pTask->u.IsaSetIRQ.uTagSrc = uTagSrc;
860
861 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
862 return false;
863}
864
865
866/**
867 * PDMDevHlpCallR0 helper.
868 *
869 * @returns See PFNPDMDEVREQHANDLERR0.
870 * @param pVM The cross context VM structure. (For validation.)
871 * @param pReq Pointer to the request buffer.
872 */
873VMMR0_INT_DECL(int) PDMR0DeviceCallReqHandler(PVM pVM, PPDMDEVICECALLREQHANDLERREQ pReq)
874{
875 /*
876 * Validate input and make the call.
877 */
878 AssertPtrReturn(pVM, VERR_INVALID_POINTER);
879 AssertPtrReturn(pReq, VERR_INVALID_POINTER);
880 AssertMsgReturn(pReq->Hdr.cbReq == sizeof(*pReq), ("%#x != %#x\n", pReq->Hdr.cbReq, sizeof(*pReq)), VERR_INVALID_PARAMETER);
881
882 PPDMDEVINS pDevIns = pReq->pDevInsR0;
883 AssertPtrReturn(pDevIns, VERR_INVALID_POINTER);
884 AssertReturn(pDevIns->Internal.s.pVMR0 == pVM, VERR_INVALID_PARAMETER);
885
886 PFNPDMDEVREQHANDLERR0 pfnReqHandlerR0 = pReq->pfnReqHandlerR0;
887 AssertPtrReturn(pfnReqHandlerR0, VERR_INVALID_POINTER);
888
889 return pfnReqHandlerR0(pDevIns, pReq->uOperation, pReq->u64Arg);
890}
891
Note: See TracBrowser for help on using the repository browser.

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