VirtualBox

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

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

VMM: Refactoring VMMR0/* and VMMRZ/* to use VMCC & VMMCPUCC. bugref:9217

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