VirtualBox

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

Last change on this file since 27147 was 26376, checked in by vboxsync, 15 years ago

HPET: reworking locking per Knut suggestions

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 24.7 KB
Line 
1/* $Id: PDMR0Device.cpp 26376 2010-02-09 14:25:28Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, R0 Device parts.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_PDM_DEVICE
27#include "PDMInternal.h"
28#include <VBox/pdm.h>
29#include <VBox/pgm.h>
30#include <VBox/mm.h>
31#include <VBox/vm.h>
32#include <VBox/vmm.h>
33#include <VBox/patm.h>
34#include <VBox/hwaccm.h>
35
36#include <VBox/log.h>
37#include <VBox/err.h>
38#include <VBox/gvmm.h>
39#include <iprt/asm.h>
40#include <iprt/assert.h>
41#include <iprt/string.h>
42
43
44/*******************************************************************************
45* Global Variables *
46*******************************************************************************/
47RT_C_DECLS_BEGIN
48extern DECLEXPORT(const PDMDEVHLPR0) g_pdmR0DevHlp;
49extern DECLEXPORT(const PDMPICHLPR0) g_pdmR0PicHlp;
50extern DECLEXPORT(const PDMAPICHLPR0) g_pdmR0ApicHlp;
51extern DECLEXPORT(const PDMIOAPICHLPR0) g_pdmR0IoApicHlp;
52extern DECLEXPORT(const PDMPCIHLPR0) g_pdmR0PciHlp;
53extern DECLEXPORT(const PDMHPETHLPR0) g_pdmR0HpetHlp;
54extern DECLEXPORT(const PDMDRVHLPR0) g_pdmR0DrvHlp;
55RT_C_DECLS_END
56
57
58/*******************************************************************************
59* Internal Functions *
60*******************************************************************************/
61static void pdmR0IsaSetIrq(PVM pVM, int iIrq, int iLevel);
62static void pdmR0IoApicSetIrq(PVM pVM, int iIrq, int iLevel);
63
64
65
66
67/** @name Ring-0 Device Helpers
68 * @{
69 */
70
71/** @interface_method_impl{PDMDEVHLPR0,pfnPCISetIrq} */
72static DECLCALLBACK(void) pdmR0DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
73{
74 PDMDEV_ASSERT_DEVINS(pDevIns);
75 LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
76
77 PVM pVM = pDevIns->Internal.s.pVMR0;
78 PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR0;
79 PPDMPCIBUS pPciBus = pDevIns->Internal.s.pPciBusR0;
80 if ( pPciDev
81 && pPciBus
82 && pPciBus->pDevInsR0)
83 {
84 pdmLock(pVM);
85 pPciBus->pfnSetIrqR0(pPciBus->pDevInsR0, pPciDev, iIrq, iLevel);
86 pdmUnlock(pVM);
87 }
88 else
89 {
90 /* queue for ring-3 execution. */
91 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueR0);
92 if (pTask)
93 {
94 pTask->enmOp = PDMDEVHLPTASKOP_PCI_SET_IRQ;
95 pTask->pDevInsR3 = PDMDEVINS_2_R3PTR(pDevIns);
96 pTask->u.SetIRQ.iIrq = iIrq;
97 pTask->u.SetIRQ.iLevel = iLevel;
98
99 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
100 }
101 else
102 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
103 }
104
105 LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: returns void\n", pDevIns, pDevIns->iInstance));
106}
107
108
109/** @interface_method_impl{PDMDEVHLPR0,pfnPCISetIrq} */
110static DECLCALLBACK(void) pdmR0DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
111{
112 PDMDEV_ASSERT_DEVINS(pDevIns);
113 LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
114
115 pdmR0IsaSetIrq(pDevIns->Internal.s.pVMR0, iIrq, iLevel);
116
117 LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: returns void\n", pDevIns, pDevIns->iInstance));
118}
119
120
121/** @interface_method_impl{PDMDEVHLPR0,pfnPhysRead} */
122static DECLCALLBACK(int) pdmR0DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
123{
124 PDMDEV_ASSERT_DEVINS(pDevIns);
125 LogFlow(("pdmR0DevHlp_PhysRead: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
126 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
127
128 int rc = PGMPhysRead(pDevIns->Internal.s.pVMR0, GCPhys, pvBuf, cbRead);
129 AssertRC(rc); /** @todo track down the users for this bugger. */
130
131 Log(("pdmR0DevHlp_PhysRead: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, rc));
132 return rc;
133}
134
135
136/** @interface_method_impl{PDMDEVHLPR0,pfnPhysWrite} */
137static DECLCALLBACK(int) pdmR0DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
138{
139 PDMDEV_ASSERT_DEVINS(pDevIns);
140 LogFlow(("pdmR0DevHlp_PhysWrite: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
141 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
142
143 int rc = PGMPhysWrite(pDevIns->Internal.s.pVMR0, GCPhys, pvBuf, cbWrite);
144 AssertRC(rc); /** @todo track down the users for this bugger. */
145
146 Log(("pdmR0DevHlp_PhysWrite: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, rc));
147 return rc;
148}
149
150
151/** @interface_method_impl{PDMDEVHLPR0,pfnA20IsEnabled} */
152static DECLCALLBACK(bool) pdmR0DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
153{
154 PDMDEV_ASSERT_DEVINS(pDevIns);
155 LogFlow(("pdmR0DevHlp_A20IsEnabled: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
156
157 bool fEnabled = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pVMR0));
158
159 Log(("pdmR0DevHlp_A20IsEnabled: caller=%p/%d: returns %RTbool\n", pDevIns, pDevIns->iInstance, fEnabled));
160 return fEnabled;
161}
162
163
164/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetError} */
165static DECLCALLBACK(int) pdmR0DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
166{
167 PDMDEV_ASSERT_DEVINS(pDevIns);
168 va_list args;
169 va_start(args, pszFormat);
170 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR0, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
171 va_end(args);
172 return rc;
173}
174
175
176/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetErrorV} */
177static DECLCALLBACK(int) pdmR0DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
178{
179 PDMDEV_ASSERT_DEVINS(pDevIns);
180 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR0, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
181 return rc;
182}
183
184
185/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetRuntimeError} */
186static DECLCALLBACK(int) pdmR0DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
187{
188 PDMDEV_ASSERT_DEVINS(pDevIns);
189 va_list va;
190 va_start(va, pszFormat);
191 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR0, fFlags, pszErrorId, pszFormat, va);
192 va_end(va);
193 return rc;
194}
195
196
197/** @interface_method_impl{PDMDEVHLPR0,pfnVMSetRuntimeErrorV} */
198static DECLCALLBACK(int) pdmR0DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
199{
200 PDMDEV_ASSERT_DEVINS(pDevIns);
201 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR0, fFlags, pszErrorId, pszFormat, va);
202 return rc;
203}
204
205
206/** @copydoc PDMDEVHLPR0::pdmR0DevHlp_PATMSetMMIOPatchInfo*/
207static DECLCALLBACK(int) pdmR0DevHlp_PATMSetMMIOPatchInfo(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPTR pCachedData)
208{
209 PDMDEV_ASSERT_DEVINS(pDevIns);
210 LogFlow(("pdmR0DevHlp_PATMSetMMIOPatchInfo: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
211
212 AssertFailed();
213
214/* return PATMSetMMIOPatchInfo(pDevIns->Internal.s.pVMR0, GCPhys, pCachedData); */
215 return VINF_SUCCESS;
216}
217
218
219/** @interface_method_impl{PDMDEVHLPR0,pfnGetVM} */
220static DECLCALLBACK(PVM) pdmR0DevHlp_GetVM(PPDMDEVINS pDevIns)
221{
222 PDMDEV_ASSERT_DEVINS(pDevIns);
223 LogFlow(("pdmR0DevHlp_GetVM: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
224 return pDevIns->Internal.s.pVMR0;
225}
226
227
228/** @interface_method_impl{PDMDEVHLPR0,pfnCanEmulateIoBlock} */
229static DECLCALLBACK(bool) pdmR0DevHlp_CanEmulateIoBlock(PPDMDEVINS pDevIns)
230{
231 PDMDEV_ASSERT_DEVINS(pDevIns);
232 LogFlow(("pdmR0DevHlp_GetVM: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
233 return HWACCMCanEmulateIoBlock(VMMGetCpu(pDevIns->Internal.s.pVMR0));
234}
235
236
237/** @interface_method_impl{PDMDEVHLPR0,pfnGetVMCPU} */
238static DECLCALLBACK(PVMCPU) pdmR0DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
239{
240 PDMDEV_ASSERT_DEVINS(pDevIns);
241 LogFlow(("pdmR0DevHlp_GetVMCPU: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
242 return VMMGetCpu(pDevIns->Internal.s.pVMR0);
243}
244
245
246/**
247 * The Ring-0 Device Helper Callbacks.
248 */
249extern DECLEXPORT(const PDMDEVHLPR0) g_pdmR0DevHlp =
250{
251 PDM_DEVHLPR0_VERSION,
252 pdmR0DevHlp_PCISetIrq,
253 pdmR0DevHlp_ISASetIrq,
254 pdmR0DevHlp_PhysRead,
255 pdmR0DevHlp_PhysWrite,
256 pdmR0DevHlp_A20IsEnabled,
257 pdmR0DevHlp_VMSetError,
258 pdmR0DevHlp_VMSetErrorV,
259 pdmR0DevHlp_VMSetRuntimeError,
260 pdmR0DevHlp_VMSetRuntimeErrorV,
261 pdmR0DevHlp_PATMSetMMIOPatchInfo,
262 pdmR0DevHlp_GetVM,
263 pdmR0DevHlp_CanEmulateIoBlock,
264 pdmR0DevHlp_GetVMCPU,
265 PDM_DEVHLPR0_VERSION
266};
267
268/** @} */
269
270
271
272
273/** @name PIC Ring-0 Helpers
274 * @{
275 */
276
277/** @interface_method_impl{PDMPICHLPR0,pfnSetInterruptFF} */
278static DECLCALLBACK(void) pdmR0PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
279{
280 PDMDEV_ASSERT_DEVINS(pDevIns);
281 PVM pVM = pDevIns->Internal.s.pVMR0;
282
283 if (pVM->pdm.s.Apic.pfnLocalInterruptR0)
284 {
285 LogFlow(("pdmR0PicHlp_SetInterruptFF: caller='%p'/%d: Setting local interrupt on LAPIC\n",
286 pDevIns, pDevIns->iInstance));
287 /* Raise the LAPIC's LINT0 line instead of signaling the CPU directly. */
288 pVM->pdm.s.Apic.pfnLocalInterruptR0(pVM->pdm.s.Apic.pDevInsR0, 0, 1);
289 return;
290 }
291
292 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
293
294 LogFlow(("pdmR0PicHlp_SetInterruptFF: caller=%p/%d: VMCPU_FF_INTERRUPT_PIC %d -> 1\n",
295 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_PIC)));
296
297 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC);
298}
299
300
301/** @interface_method_impl{PDMPICHLPR0,pfnClearInterruptFF} */
302static DECLCALLBACK(void) pdmR0PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
303{
304 PDMDEV_ASSERT_DEVINS(pDevIns);
305 PVM pVM = pDevIns->Internal.s.pVMR0;
306
307 if (pVM->pdm.s.Apic.pfnLocalInterruptR0)
308 {
309 /* Raise the LAPIC's LINT0 line instead of signaling the CPU directly. */
310 LogFlow(("pdmR0PicHlp_ClearInterruptFF: caller='%s'/%d: Clearing local interrupt on LAPIC\n",
311 pDevIns, pDevIns->iInstance));
312 /* Lower the LAPIC's LINT0 line instead of signaling the CPU directly. */
313 pVM->pdm.s.Apic.pfnLocalInterruptR0(pVM->pdm.s.Apic.pDevInsR0, 0, 0);
314 return;
315 }
316
317 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
318
319 LogFlow(("pdmR0PicHlp_ClearInterruptFF: caller=%p/%d: VMCPU_FF_INTERRUPT_PIC %d -> 0\n",
320 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_PIC)));
321
322 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
323}
324
325
326/** @interface_method_impl{PDMPICHLPR0,pfnLock} */
327static DECLCALLBACK(int) pdmR0PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
328{
329 PDMDEV_ASSERT_DEVINS(pDevIns);
330 return pdmLockEx(pDevIns->Internal.s.pVMR0, rc);
331}
332
333
334/** @interface_method_impl{PDMPICHLPR0,pfnUnlock} */
335static DECLCALLBACK(void) pdmR0PicHlp_Unlock(PPDMDEVINS pDevIns)
336{
337 PDMDEV_ASSERT_DEVINS(pDevIns);
338 pdmUnlock(pDevIns->Internal.s.pVMR0);
339}
340
341
342/**
343 * The Ring-0 PIC Helper Callbacks.
344 */
345extern DECLEXPORT(const PDMPICHLPR0) g_pdmR0PicHlp =
346{
347 PDM_PICHLPR0_VERSION,
348 pdmR0PicHlp_SetInterruptFF,
349 pdmR0PicHlp_ClearInterruptFF,
350 pdmR0PicHlp_Lock,
351 pdmR0PicHlp_Unlock,
352 PDM_PICHLPR0_VERSION
353};
354
355/** @} */
356
357
358
359
360/** @name APIC Ring-0 Helpers
361 * @{
362 */
363
364/** @interface_method_impl{PDMAPICHLPR0,pfnSetInterruptFF} */
365static DECLCALLBACK(void) pdmR0ApicHlp_SetInterruptFF(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu)
366{
367 PDMDEV_ASSERT_DEVINS(pDevIns);
368 PVM pVM = pDevIns->Internal.s.pVMR0;
369 PVMCPU pVCpu = &pVM->aCpus[idCpu];
370
371 AssertReturnVoid(idCpu < pVM->cCpus);
372
373 LogFlow(("pdmR0ApicHlp_SetInterruptFF: CPU%d=caller=%p/%d: VM_FF_INTERRUPT %d -> 1 (CPU%d)\n",
374 VMMGetCpuId(pVM), pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_APIC), idCpu));
375
376 switch (enmType)
377 {
378 case PDMAPICIRQ_HARDWARE:
379 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC);
380 break;
381 case PDMAPICIRQ_NMI:
382 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI);
383 break;
384 case PDMAPICIRQ_SMI:
385 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_SMI);
386 break;
387 case PDMAPICIRQ_EXTINT:
388 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC);
389 break;
390 default:
391 AssertMsgFailed(("enmType=%d\n", enmType));
392 break;
393 }
394
395 /* We need to wait up the target CPU. */
396 if (VMMGetCpuId(pVM) != idCpu)
397 {
398 switch (VMCPU_GET_STATE(pVCpu))
399 {
400 case VMCPUSTATE_STARTED_EXEC:
401 GVMMR0SchedPokeEx(pVM, pVCpu->idCpu, false /* don't take the used lock */);
402 break;
403
404 case VMCPUSTATE_STARTED_HALTED:
405 GVMMR0SchedWakeUpEx(pVM, pVCpu->idCpu, false /* don't take the used lock */);
406 break;
407
408 default:
409 break; /* nothing to do in other states. */
410 }
411 }
412}
413
414
415/** @interface_method_impl{PDMAPICHLPR0,pfnClearInterruptFF} */
416static DECLCALLBACK(void) pdmR0ApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu)
417{
418 PDMDEV_ASSERT_DEVINS(pDevIns);
419 PVM pVM = pDevIns->Internal.s.pVMR0;
420 PVMCPU pVCpu = &pVM->aCpus[idCpu];
421
422 AssertReturnVoid(idCpu < pVM->cCpus);
423
424 LogFlow(("pdmR0ApicHlp_ClearInterruptFF: caller=%p/%d: VM_FF_INTERRUPT %d -> 0\n",
425 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_APIC)));
426
427 /* Note: NMI/SMI can't be cleared. */
428 switch (enmType)
429 {
430 case PDMAPICIRQ_HARDWARE:
431 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_APIC);
432 break;
433 case PDMAPICIRQ_EXTINT:
434 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
435 break;
436 default:
437 AssertMsgFailed(("enmType=%d\n", enmType));
438 break;
439 }
440}
441
442
443/** @interface_method_impl{PDMAPICHLPR0,pfnChangeFeature} */
444static DECLCALLBACK(void) pdmR0ApicHlp_ChangeFeature(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion)
445{
446 PDMDEV_ASSERT_DEVINS(pDevIns);
447 LogFlow(("pdmR0ApicHlp_ChangeFeature: caller=%p/%d: version=%d\n", pDevIns, pDevIns->iInstance, (int)enmVersion));
448 switch (enmVersion)
449 {
450 case PDMAPICVERSION_NONE:
451 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR0, CPUMCPUIDFEATURE_APIC);
452 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR0, CPUMCPUIDFEATURE_X2APIC);
453 break;
454 case PDMAPICVERSION_APIC:
455 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMR0, CPUMCPUIDFEATURE_APIC);
456 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR0, CPUMCPUIDFEATURE_X2APIC);
457 break;
458 case PDMAPICVERSION_X2APIC:
459 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMR0, CPUMCPUIDFEATURE_X2APIC);
460 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMR0, CPUMCPUIDFEATURE_APIC);
461 break;
462 default:
463 AssertMsgFailed(("Unknown APIC version: %d\n", (int)enmVersion));
464 }
465}
466
467
468/** @interface_method_impl{PDMAPICHLPR0,pfnLock} */
469static DECLCALLBACK(int) pdmR0ApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
470{
471 PDMDEV_ASSERT_DEVINS(pDevIns);
472 return pdmLockEx(pDevIns->Internal.s.pVMR0, rc);
473}
474
475
476/** @interface_method_impl{PDMAPICHLPR0,pfnUnlock} */
477static DECLCALLBACK(void) pdmR0ApicHlp_Unlock(PPDMDEVINS pDevIns)
478{
479 PDMDEV_ASSERT_DEVINS(pDevIns);
480 pdmUnlock(pDevIns->Internal.s.pVMR0);
481}
482
483
484/** @interface_method_impl{PDMAPICHLPR0,pfnGetCpuId} */
485static DECLCALLBACK(VMCPUID) pdmR0ApicHlp_GetCpuId(PPDMDEVINS pDevIns)
486{
487 PDMDEV_ASSERT_DEVINS(pDevIns);
488 return VMMGetCpuId(pDevIns->Internal.s.pVMR0);
489}
490
491
492/**
493 * The Ring-0 APIC Helper Callbacks.
494 */
495extern DECLEXPORT(const PDMAPICHLPR0) g_pdmR0ApicHlp =
496{
497 PDM_APICHLPR0_VERSION,
498 pdmR0ApicHlp_SetInterruptFF,
499 pdmR0ApicHlp_ClearInterruptFF,
500 pdmR0ApicHlp_ChangeFeature,
501 pdmR0ApicHlp_Lock,
502 pdmR0ApicHlp_Unlock,
503 pdmR0ApicHlp_GetCpuId,
504 PDM_APICHLPR0_VERSION
505};
506
507/** @} */
508
509
510
511
512/** @name I/O APIC Ring-0 Helpers
513 * @{
514 */
515
516/** @interface_method_impl{PDMIOAPICHLPR0,pfnApicBusDeliver} */
517static DECLCALLBACK(int) pdmR0IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
518 uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode)
519{
520 PDMDEV_ASSERT_DEVINS(pDevIns);
521 PVM pVM = pDevIns->Internal.s.pVMR0;
522 LogFlow(("pdmR0IoApicHlp_ApicBusDeliver: caller=%p/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8\n",
523 pDevIns, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode));
524 Assert(pVM->pdm.s.Apic.pDevInsR0);
525 if (pVM->pdm.s.Apic.pfnBusDeliverR0)
526 return pVM->pdm.s.Apic.pfnBusDeliverR0(pVM->pdm.s.Apic.pDevInsR0, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode);
527 return VINF_SUCCESS;
528}
529
530
531/** @interface_method_impl{PDMIOAPICHLPR0,pfnLock} */
532static DECLCALLBACK(int) pdmR0IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
533{
534 PDMDEV_ASSERT_DEVINS(pDevIns);
535 return pdmLockEx(pDevIns->Internal.s.pVMR0, rc);
536}
537
538
539/** @interface_method_impl{PDMIOAPICHLPR0,pfnUnlock} */
540static DECLCALLBACK(void) pdmR0IoApicHlp_Unlock(PPDMDEVINS pDevIns)
541{
542 PDMDEV_ASSERT_DEVINS(pDevIns);
543 pdmUnlock(pDevIns->Internal.s.pVMR0);
544}
545
546
547/**
548 * The Ring-0 I/O APIC Helper Callbacks.
549 */
550extern DECLEXPORT(const PDMIOAPICHLPR0) g_pdmR0IoApicHlp =
551{
552 PDM_IOAPICHLPR0_VERSION,
553 pdmR0IoApicHlp_ApicBusDeliver,
554 pdmR0IoApicHlp_Lock,
555 pdmR0IoApicHlp_Unlock,
556 PDM_IOAPICHLPR0_VERSION
557};
558
559/** @} */
560
561
562
563
564/** @name PCI Bus Ring-0 Helpers
565 * @{
566 */
567
568/** @interface_method_impl{PDMPCIHLPR0,pfnIsaSetIrq} */
569static DECLCALLBACK(void) pdmR0PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
570{
571 PDMDEV_ASSERT_DEVINS(pDevIns);
572 Log4(("pdmR0PciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
573 pdmR0IsaSetIrq(pDevIns->Internal.s.pVMR0, iIrq, iLevel);
574}
575
576
577/** @interface_method_impl{PDMPCIHLPR0,pfnIoApicSetIrq} */
578static DECLCALLBACK(void) pdmR0PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
579{
580 PDMDEV_ASSERT_DEVINS(pDevIns);
581 Log4(("pdmR0PciHlp_IoApicSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
582 pdmR0IoApicSetIrq(pDevIns->Internal.s.pVMR0, iIrq, iLevel);
583}
584
585
586/** @interface_method_impl{PDMPCIHLPR0,pfnLock} */
587static DECLCALLBACK(int) pdmR0PciHlp_Lock(PPDMDEVINS pDevIns, int rc)
588{
589 PDMDEV_ASSERT_DEVINS(pDevIns);
590 return pdmLockEx(pDevIns->Internal.s.pVMR0, rc);
591}
592
593
594/** @interface_method_impl{PDMPCIHLPR0,pfnUnlock} */
595static DECLCALLBACK(void) pdmR0PciHlp_Unlock(PPDMDEVINS pDevIns)
596{
597 PDMDEV_ASSERT_DEVINS(pDevIns);
598 pdmUnlock(pDevIns->Internal.s.pVMR0);
599}
600
601
602/**
603 * The Ring-0 PCI Bus Helper Callbacks.
604 */
605extern DECLEXPORT(const PDMPCIHLPR0) g_pdmR0PciHlp =
606{
607 PDM_PCIHLPR0_VERSION,
608 pdmR0PciHlp_IsaSetIrq,
609 pdmR0PciHlp_IoApicSetIrq,
610 pdmR0PciHlp_Lock,
611 pdmR0PciHlp_Unlock,
612 PDM_PCIHLPR0_VERSION, /* the end */
613};
614
615/** @} */
616
617
618
619
620/** @name HPET Ring-0 Helpers
621 * @{
622 */
623
624/**
625 * The Ring-0 HPET Helper Callbacks.
626 */
627extern DECLEXPORT(const PDMHPETHLPR0) g_pdmR0HpetHlp =
628{
629 PDM_HPETHLPR0_VERSION,
630 PDM_HPETHLPR0_VERSION, /* the end */
631};
632
633/** @} */
634
635
636
637
638/** @name Ring-0 Context Driver Helpers
639 * @{
640 */
641
642/** @interface_method_impl{PDMDRVHLPR0,pfnVMSetError} */
643static DECLCALLBACK(int) pdmR0DrvHlp_VMSetError(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
644{
645 PDMDRV_ASSERT_DRVINS(pDrvIns);
646 va_list args;
647 va_start(args, pszFormat);
648 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMR0, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
649 va_end(args);
650 return rc;
651}
652
653
654/** @interface_method_impl{PDMDRVHLPR0,pfnVMSetErrorV} */
655static DECLCALLBACK(int) pdmR0DrvHlp_VMSetErrorV(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
656{
657 PDMDRV_ASSERT_DRVINS(pDrvIns);
658 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMR0, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
659 return rc;
660}
661
662
663/** @interface_method_impl{PDMDRVHLPR0,pfnVMSetRuntimeError} */
664static DECLCALLBACK(int) pdmR0DrvHlp_VMSetRuntimeError(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
665{
666 PDMDRV_ASSERT_DRVINS(pDrvIns);
667 va_list va;
668 va_start(va, pszFormat);
669 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMR0, fFlags, pszErrorId, pszFormat, va);
670 va_end(va);
671 return rc;
672}
673
674
675/** @interface_method_impl{PDMDRVHLPR0,pfnVMSetErrorV} */
676static DECLCALLBACK(int) pdmR0DrvHlp_VMSetRuntimeErrorV(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
677{
678 PDMDRV_ASSERT_DRVINS(pDrvIns);
679 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMR0, fFlags, pszErrorId, pszFormat, va);
680 return rc;
681}
682
683
684/** @interface_method_impl{PDMDRVHLPR0,pfnAssertEMT} */
685static DECLCALLBACK(bool) pdmR0DrvHlp_AssertEMT(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
686{
687 PDMDRV_ASSERT_DRVINS(pDrvIns);
688 if (VM_IS_EMT(pDrvIns->Internal.s.pVMR0))
689 return true;
690
691 RTAssertMsg1Weak("AssertEMT", iLine, pszFile, pszFunction);
692 RTAssertPanic();
693 return false;
694}
695
696
697/** @interface_method_impl{PDMDRVHLPR0,pfnAssertOther} */
698static DECLCALLBACK(bool) pdmR0DrvHlp_AssertOther(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
699{
700 PDMDRV_ASSERT_DRVINS(pDrvIns);
701 if (!VM_IS_EMT(pDrvIns->Internal.s.pVMR0))
702 return true;
703
704 RTAssertMsg1Weak("AssertOther", iLine, pszFile, pszFunction);
705 RTAssertPanic();
706 return false;
707}
708
709
710/**
711 * The Raw-Mode Context Driver Helper Callbacks.
712 */
713extern DECLEXPORT(const PDMDRVHLPR0) g_pdmR0DrvHlp =
714{
715 PDM_DRVHLPRC_VERSION,
716 pdmR0DrvHlp_VMSetError,
717 pdmR0DrvHlp_VMSetErrorV,
718 pdmR0DrvHlp_VMSetRuntimeError,
719 pdmR0DrvHlp_VMSetRuntimeErrorV,
720 pdmR0DrvHlp_AssertEMT,
721 pdmR0DrvHlp_AssertOther,
722 PDM_DRVHLPRC_VERSION
723};
724
725/** @} */
726
727
728
729
730/**
731 * Sets an irq on the I/O APIC.
732 *
733 * @param pVM The VM handle.
734 * @param iIrq The irq.
735 * @param iLevel The new level.
736 */
737static void pdmR0IsaSetIrq(PVM pVM, int iIrq, int iLevel)
738{
739 if ( ( pVM->pdm.s.IoApic.pDevInsR0
740 || !pVM->pdm.s.IoApic.pDevInsR3)
741 && ( pVM->pdm.s.Pic.pDevInsR0
742 || !pVM->pdm.s.Pic.pDevInsR3))
743 {
744 pdmLock(pVM);
745 if (pVM->pdm.s.Pic.pDevInsR0)
746 pVM->pdm.s.Pic.pfnSetIrqR0(pVM->pdm.s.Pic.pDevInsR0, iIrq, iLevel);
747 if (pVM->pdm.s.IoApic.pDevInsR0)
748 pVM->pdm.s.IoApic.pfnSetIrqR0(pVM->pdm.s.IoApic.pDevInsR0, iIrq, iLevel);
749 pdmUnlock(pVM);
750 }
751 else
752 {
753 /* queue for ring-3 execution. */
754 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueR0);
755 if (pTask)
756 {
757 pTask->enmOp = PDMDEVHLPTASKOP_ISA_SET_IRQ;
758 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
759 pTask->u.SetIRQ.iIrq = iIrq;
760 pTask->u.SetIRQ.iLevel = iLevel;
761
762 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
763 }
764 else
765 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
766 }
767}
768
769
770/**
771 * Sets an irq on the I/O APIC.
772 *
773 * @param pVM The VM handle.
774 * @param iIrq The irq.
775 * @param iLevel The new level.
776 */
777static void pdmR0IoApicSetIrq(PVM pVM, int iIrq, int iLevel)
778{
779 if (pVM->pdm.s.IoApic.pDevInsR0)
780 {
781 pdmLock(pVM);
782 pVM->pdm.s.IoApic.pfnSetIrqR0(pVM->pdm.s.IoApic.pDevInsR0, iIrq, iLevel);
783 pdmUnlock(pVM);
784 }
785 else if (pVM->pdm.s.IoApic.pDevInsR3)
786 {
787 /* queue for ring-3 execution. */
788 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueR0);
789 if (pTask)
790 {
791 pTask->enmOp = PDMDEVHLPTASKOP_IOAPIC_SET_IRQ;
792 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
793 pTask->u.SetIRQ.iIrq = iIrq;
794 pTask->u.SetIRQ.iLevel = iLevel;
795
796 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);
797 }
798 else
799 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
800 }
801}
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