VirtualBox

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

Last change on this file since 68916 was 68594, checked in by vboxsync, 8 years ago

PDM: Address the todos for cleaning up the PDMDEVHLP structure, bring the reserved slots back to the nominal numver and bump the major version (20 ended up being used by 5.1). Eliminate redundant PDMDEVHLP version dependent conditional compilation

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