VirtualBox

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

Last change on this file since 26066 was 26001, checked in by vboxsync, 15 years ago

PDM,*: Redid the PDM structure versions. Check the instance and helper versions in every device and driver constructor.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette