VirtualBox

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

Last change on this file since 43667 was 43387, checked in by vboxsync, 12 years ago

VMM: HM cleanup.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use