VirtualBox

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

Last change on this file since 72485 was 69111, checked in by vboxsync, 7 years ago

(C) year

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