VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMGC/PDMGCDevice.cpp@ 26001

Last change on this file since 26001 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: 20.9 KB
Line 
1/* $Id: PDMGCDevice.cpp 26001 2010-01-25 14:21:13Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, RC 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
35#include <VBox/log.h>
36#include <VBox/err.h>
37#include <iprt/asm.h>
38#include <iprt/assert.h>
39#include <iprt/string.h>
40
41
42/*******************************************************************************
43* Global Variables *
44*******************************************************************************/
45RT_C_DECLS_BEGIN
46extern DECLEXPORT(const PDMDEVHLPRC) g_pdmRCDevHlp;
47extern DECLEXPORT(const PDMPICHLPRC) g_pdmRCPicHlp;
48extern DECLEXPORT(const PDMAPICHLPRC) g_pdmRCApicHlp;
49extern DECLEXPORT(const PDMIOAPICHLPRC) g_pdmRCIoApicHlp;
50extern DECLEXPORT(const PDMPCIHLPRC) g_pdmRCPciHlp;
51extern DECLEXPORT(const PDMHPETHLPRC) g_pdmRCHpetHlp;
52RT_C_DECLS_END
53
54
55/*******************************************************************************
56* Internal Functions *
57*******************************************************************************/
58static void pdmRCIsaSetIrq(PVM pVM, int iIrq, int iLevel);
59static void pdmRCIoApicSetIrq(PVM pVM, int iIrq, int iLevel);
60
61
62
63
64/** @name Raw-Mode Context Device Helpers
65 * @{
66 */
67
68/** @copydoc PDMDEVHLPRC::pfnPCISetIrq */
69static DECLCALLBACK(void) pdmGCDevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
70{
71 PDMDEV_ASSERT_DEVINS(pDevIns);
72 LogFlow(("pdmGCDevHlp_PCISetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
73
74 PVM pVM = pDevIns->Internal.s.pVMRC;
75 PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceRC;
76 PPDMPCIBUS pPciBus = pDevIns->Internal.s.pPciBusRC;
77 if ( pPciDev
78 && pPciBus
79 && pPciBus->pDevInsRC)
80 {
81 pdmLock(pVM);
82 pPciBus->pfnSetIrqRC(pPciBus->pDevInsRC, pPciDev, iIrq, iLevel);
83 pdmUnlock(pVM);
84 }
85 else
86 {
87 /* queue for ring-3 execution. */
88 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
89 if (pTask)
90 {
91 pTask->enmOp = PDMDEVHLPTASKOP_PCI_SET_IRQ;
92 pTask->pDevInsR3 = PDMDEVINS_2_R3PTR(pDevIns);
93 pTask->u.SetIRQ.iIrq = iIrq;
94 pTask->u.SetIRQ.iLevel = iLevel;
95
96 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
97 }
98 else
99 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
100 }
101
102 LogFlow(("pdmGCDevHlp_PCISetIrq: caller=%p/%d: returns void\n", pDevIns, pDevIns->iInstance));
103}
104
105
106/** @copydoc PDMDEVHLPRC::pfnPCISetIrq */
107static DECLCALLBACK(void) pdmGCDevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
108{
109 PDMDEV_ASSERT_DEVINS(pDevIns);
110 LogFlow(("pdmGCDevHlp_ISASetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
111
112 pdmRCIsaSetIrq(pDevIns->Internal.s.pVMRC, iIrq, iLevel);
113
114 LogFlow(("pdmGCDevHlp_ISASetIrq: caller=%p/%d: returns void\n", pDevIns, pDevIns->iInstance));
115}
116
117
118/** @copydoc PDMDEVHLPRC::pfnPhysRead */
119static DECLCALLBACK(int) pdmGCDevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
120{
121 PDMDEV_ASSERT_DEVINS(pDevIns);
122 LogFlow(("pdmGCDevHlp_PhysRead: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
123 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
124
125 int rc = PGMPhysRead(pDevIns->Internal.s.pVMRC, GCPhys, pvBuf, cbRead);
126 AssertRC(rc); /** @todo track down the users for this bugger. */
127
128 Log(("pdmGCDevHlp_PhysRead: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, rc));
129 return rc;
130}
131
132
133/** @copydoc PDMDEVHLPRC::pfnPhysWrite */
134static DECLCALLBACK(int) pdmGCDevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
135{
136 PDMDEV_ASSERT_DEVINS(pDevIns);
137 LogFlow(("pdmGCDevHlp_PhysWrite: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
138 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
139
140 int rc = PGMPhysWrite(pDevIns->Internal.s.pVMRC, GCPhys, pvBuf, cbWrite);
141 AssertRC(rc); /** @todo track down the users for this bugger. */
142
143 Log(("pdmGCDevHlp_PhysWrite: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, rc));
144 return rc;
145}
146
147
148/** @copydoc PDMDEVHLPRC::pfnA20IsEnabled */
149static DECLCALLBACK(bool) pdmGCDevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
150{
151 PDMDEV_ASSERT_DEVINS(pDevIns);
152 LogFlow(("pdmGCDevHlp_A20IsEnabled: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
153
154 bool fEnabled = PGMPhysIsA20Enabled(VMMGetCpu0(pDevIns->Internal.s.pVMRC));
155
156 Log(("pdmGCDevHlp_A20IsEnabled: caller=%p/%d: returns %RTbool\n", pDevIns, pDevIns->iInstance, fEnabled));
157 return fEnabled;
158}
159
160
161/** @copydoc PDMDEVHLPRC::pfnVMSetError */
162static DECLCALLBACK(int) pdmGCDevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
163{
164 PDMDEV_ASSERT_DEVINS(pDevIns);
165 va_list args;
166 va_start(args, pszFormat);
167 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
168 va_end(args);
169 return rc;
170}
171
172
173/** @copydoc PDMDEVHLPRC::pfnVMSetErrorV */
174static DECLCALLBACK(int) pdmGCDevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
175{
176 PDMDEV_ASSERT_DEVINS(pDevIns);
177 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
178 return rc;
179}
180
181
182/** @copydoc PDMDEVHLPRC::pfnVMSetRuntimeError */
183static DECLCALLBACK(int) pdmGCDevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
184{
185 PDMDEV_ASSERT_DEVINS(pDevIns);
186 va_list va;
187 va_start(va, pszFormat);
188 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
189 va_end(va);
190 return rc;
191}
192
193
194/** @copydoc PDMDEVHLPRC::pfnVMSetErrorV */
195static DECLCALLBACK(int) pdmGCDevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
196{
197 PDMDEV_ASSERT_DEVINS(pDevIns);
198 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
199 return rc;
200}
201
202
203/** @copydoc PDMDEVHLPRC::pfnPATMSetMMIOPatchInfo */
204static DECLCALLBACK(int) pdmGCDevHlp_PATMSetMMIOPatchInfo(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPTR pCachedData)
205{
206 PDMDEV_ASSERT_DEVINS(pDevIns);
207 LogFlow(("pdmGCDevHlp_PATMSetMMIOPatchInfo: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
208
209 return PATMSetMMIOPatchInfo(pDevIns->Internal.s.pVMRC, GCPhys, (RTRCPTR)pCachedData);
210}
211
212
213/** @copydoc PDMDEVHLPRC::pfnGetVM */
214static DECLCALLBACK(PVM) pdmGCDevHlp_GetVM(PPDMDEVINS pDevIns)
215{
216 PDMDEV_ASSERT_DEVINS(pDevIns);
217 LogFlow(("pdmGCDevHlp_GetVM: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
218 return pDevIns->Internal.s.pVMRC;
219}
220
221
222/** @copydoc PDMDEVHLPRC::pfnGetVMCPU */
223static DECLCALLBACK(PVMCPU) pdmGCDevHlp_GetVMCPU(PPDMDEVINS pDevIns)
224{
225 PDMDEV_ASSERT_DEVINS(pDevIns);
226 LogFlow(("pdmGCDevHlp_GetVMCPU: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
227 return VMMGetCpu(pDevIns->Internal.s.pVMRC);
228}
229
230
231/**
232 * The Raw-Mode Context Device Helper Callbacks.
233 */
234extern DECLEXPORT(const PDMDEVHLPRC) g_pdmRCDevHlp =
235{
236 PDM_DEVHLPRC_VERSION,
237 pdmGCDevHlp_PCISetIrq,
238 pdmGCDevHlp_ISASetIrq,
239 pdmGCDevHlp_PhysRead,
240 pdmGCDevHlp_PhysWrite,
241 pdmGCDevHlp_A20IsEnabled,
242 pdmGCDevHlp_VMSetError,
243 pdmGCDevHlp_VMSetErrorV,
244 pdmGCDevHlp_VMSetRuntimeError,
245 pdmGCDevHlp_VMSetRuntimeErrorV,
246 pdmGCDevHlp_PATMSetMMIOPatchInfo,
247 pdmGCDevHlp_GetVM,
248 pdmGCDevHlp_GetVMCPU,
249 PDM_DEVHLPRC_VERSION
250};
251
252/** @} */
253
254
255
256
257/** @name PIC RC Helpers
258 * @{
259 */
260
261/** @copydoc PDMPICHLPGC::pfnSetInterruptFF */
262static DECLCALLBACK(void) pdmRCPicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
263{
264 PDMDEV_ASSERT_DEVINS(pDevIns);
265 PVM pVM = pDevIns->Internal.s.pVMRC;
266
267 if (pVM->pdm.s.Apic.pfnLocalInterruptRC)
268 {
269 LogFlow(("pdmRCPicHlp_SetInterruptFF: caller='%p'/%d: Setting local interrupt on LAPIC\n",
270 pDevIns, pDevIns->iInstance));
271 /* Raise the LAPIC's LINT0 line instead of signaling the CPU directly. */
272 pVM->pdm.s.Apic.pfnLocalInterruptRC(pVM->pdm.s.Apic.pDevInsRC, 0, 1);
273 return;
274 }
275
276 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
277
278 LogFlow(("pdmRCPicHlp_SetInterruptFF: caller=%p/%d: VMMCPU_FF_INTERRUPT_PIC %d -> 1\n",
279 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_PIC)));
280
281 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC);
282}
283
284
285/** @copydoc PDMPICHLPGC::pfnClearInterruptFF */
286static DECLCALLBACK(void) pdmRCPicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
287{
288 PDMDEV_ASSERT_DEVINS(pDevIns);
289 PVM pVM = pDevIns->Internal.s.CTX_SUFF(pVM);
290
291 if (pVM->pdm.s.Apic.pfnLocalInterruptRC)
292 {
293 /* Raise the LAPIC's LINT0 line instead of signaling the CPU directly. */
294 LogFlow(("pdmRCPicHlp_ClearInterruptFF: caller='%s'/%d: Clearing local interrupt on LAPIC\n",
295 pDevIns, pDevIns->iInstance));
296 /* Lower the LAPIC's LINT0 line instead of signaling the CPU directly. */
297 pVM->pdm.s.Apic.pfnLocalInterruptRC(pVM->pdm.s.Apic.pDevInsRC, 0, 0);
298 return;
299 }
300
301 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
302
303 LogFlow(("pdmRCPicHlp_ClearInterruptFF: caller=%p/%d: VMCPU_FF_INTERRUPT_PIC %d -> 0\n",
304 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_PIC)));
305
306 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
307}
308
309
310/** @copydoc PDMPICHLPGC::pfnLock */
311static DECLCALLBACK(int) pdmRCPicHlp_Lock(PPDMDEVINS pDevIns, int rc)
312{
313 PDMDEV_ASSERT_DEVINS(pDevIns);
314 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
315}
316
317
318/** @copydoc PDMPICHLPGC::pfnUnlock */
319static DECLCALLBACK(void) pdmRCPicHlp_Unlock(PPDMDEVINS pDevIns)
320{
321 PDMDEV_ASSERT_DEVINS(pDevIns);
322 pdmUnlock(pDevIns->Internal.s.pVMRC);
323}
324
325
326/**
327 * The Raw-Mode Context PIC Helper Callbacks.
328 */
329extern DECLEXPORT(const PDMPICHLPRC) g_pdmRCPicHlp =
330{
331 PDM_PICHLPRC_VERSION,
332 pdmRCPicHlp_SetInterruptFF,
333 pdmRCPicHlp_ClearInterruptFF,
334 pdmRCPicHlp_Lock,
335 pdmRCPicHlp_Unlock,
336 PDM_PICHLPRC_VERSION
337};
338
339/** @} */
340
341
342
343
344/** @name APIC RC Helpers
345 * @{
346 */
347
348/** @copydoc PDMAPICHLPRC::pfnSetInterruptFF */
349static DECLCALLBACK(void) pdmRCApicHlp_SetInterruptFF(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu)
350{
351 PDMDEV_ASSERT_DEVINS(pDevIns);
352 PVM pVM = pDevIns->Internal.s.pVMRC;
353 PVMCPU pVCpu = &pVM->aCpus[idCpu];
354
355 AssertReturnVoid(idCpu < pVM->cCpus);
356
357 LogFlow(("pdmRCApicHlp_SetInterruptFF: caller=%p/%d: VM_FF_INTERRUPT %d -> 1\n",
358 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_APIC)));
359 switch (enmType)
360 {
361 case PDMAPICIRQ_HARDWARE:
362 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC);
363 break;
364 case PDMAPICIRQ_NMI:
365 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI);
366 break;
367 case PDMAPICIRQ_SMI:
368 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_SMI);
369 break;
370 case PDMAPICIRQ_EXTINT:
371 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC);
372 break;
373 default:
374 AssertMsgFailed(("enmType=%d\n", enmType));
375 break;
376 }
377}
378
379
380/** @copydoc PDMAPICHLPRC::pfnClearInterruptFF */
381static DECLCALLBACK(void) pdmRCApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu)
382{
383 PDMDEV_ASSERT_DEVINS(pDevIns);
384 PVM pVM = pDevIns->Internal.s.pVMRC;
385 PVMCPU pVCpu = &pVM->aCpus[idCpu];
386
387 AssertReturnVoid(idCpu < pVM->cCpus);
388
389 LogFlow(("pdmRCApicHlp_ClearInterruptFF: caller=%p/%d: VM_FF_INTERRUPT %d -> 0\n",
390 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_APIC)));
391
392 /* Note: NMI/SMI can't be cleared. */
393 switch (enmType)
394 {
395 case PDMAPICIRQ_HARDWARE:
396 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_APIC);
397 break;
398 case PDMAPICIRQ_EXTINT:
399 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
400 break;
401 default:
402 AssertMsgFailed(("enmType=%d\n", enmType));
403 break;
404 }
405}
406
407
408/** @copydoc PDMAPICHLPRC::pfnChangeFeature */
409static DECLCALLBACK(void) pdmRCApicHlp_ChangeFeature(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion)
410{
411 PDMDEV_ASSERT_DEVINS(pDevIns);
412 LogFlow(("pdmRCApicHlp_ChangeFeature: caller=%p/%d: version=%d\n", pDevIns, pDevIns->iInstance, (int)enmVersion));
413 switch (enmVersion)
414 {
415 case PDMAPICVERSION_NONE:
416 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_APIC);
417 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_X2APIC);
418 break;
419 case PDMAPICVERSION_APIC:
420 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_APIC);
421 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_X2APIC);
422 break;
423 case PDMAPICVERSION_X2APIC:
424 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_X2APIC);
425 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_APIC);
426 break;
427 default:
428 AssertMsgFailed(("Unknown APIC version: %d\n", (int)enmVersion));
429 }
430}
431
432
433/** @copydoc PDMAPICHLPRC::pfnLock */
434static DECLCALLBACK(int) pdmRCApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
435{
436 PDMDEV_ASSERT_DEVINS(pDevIns);
437 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
438}
439
440
441/** @copydoc PDMAPICHLPRC::pfnUnlock */
442static DECLCALLBACK(void) pdmRCApicHlp_Unlock(PPDMDEVINS pDevIns)
443{
444 PDMDEV_ASSERT_DEVINS(pDevIns);
445 pdmUnlock(pDevIns->Internal.s.pVMRC);
446}
447
448
449/** @copydoc PDMAPICHLPRC::pfnGetCpuId */
450static DECLCALLBACK(VMCPUID) pdmRCApicHlp_GetCpuId(PPDMDEVINS pDevIns)
451{
452 PDMDEV_ASSERT_DEVINS(pDevIns);
453 return VMMGetCpuId(pDevIns->Internal.s.pVMRC);
454}
455
456
457/**
458 * The Raw-Mode Context APIC Helper Callbacks.
459 */
460extern DECLEXPORT(const PDMAPICHLPRC) g_pdmRCApicHlp =
461{
462 PDM_APICHLPRC_VERSION,
463 pdmRCApicHlp_SetInterruptFF,
464 pdmRCApicHlp_ClearInterruptFF,
465 pdmRCApicHlp_ChangeFeature,
466 pdmRCApicHlp_Lock,
467 pdmRCApicHlp_Unlock,
468 pdmRCApicHlp_GetCpuId,
469 PDM_APICHLPRC_VERSION
470};
471
472/** @} */
473
474
475
476
477/** @name I/O APIC RC Helpers
478 * @{
479 */
480
481/** @copydoc PDMIOAPICHLPRC::pfnApicBusDeliver */
482static DECLCALLBACK(int) pdmRCIoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
483 uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode)
484{
485 PDMDEV_ASSERT_DEVINS(pDevIns);
486 PVM pVM = pDevIns->Internal.s.pVMRC;
487 LogFlow(("pdmRCIoApicHlp_ApicBusDeliver: caller=%p/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8\n",
488 pDevIns, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode));
489 if (pVM->pdm.s.Apic.pfnBusDeliverRC)
490 return pVM->pdm.s.Apic.pfnBusDeliverRC(pVM->pdm.s.Apic.pDevInsRC, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode);
491 return VINF_SUCCESS;
492}
493
494
495/** @copydoc PDMIOAPICHLPRC::pfnLock */
496static DECLCALLBACK(int) pdmRCIoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
497{
498 PDMDEV_ASSERT_DEVINS(pDevIns);
499 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
500}
501
502
503/** @copydoc PDMIOAPICHLPRC::pfnUnlock */
504static DECLCALLBACK(void) pdmRCIoApicHlp_Unlock(PPDMDEVINS pDevIns)
505{
506 PDMDEV_ASSERT_DEVINS(pDevIns);
507 pdmUnlock(pDevIns->Internal.s.pVMRC);
508}
509
510
511/**
512 * The Raw-Mode Context I/O APIC Helper Callbacks.
513 */
514extern DECLEXPORT(const PDMIOAPICHLPRC) g_pdmRCIoApicHlp =
515{
516 PDM_IOAPICHLPRC_VERSION,
517 pdmRCIoApicHlp_ApicBusDeliver,
518 pdmRCIoApicHlp_Lock,
519 pdmRCIoApicHlp_Unlock,
520 PDM_IOAPICHLPRC_VERSION
521};
522
523/** @} */
524
525
526
527
528/** @name PCI Bus RC Helpers
529 * @{
530 */
531
532/** @copydoc PDMPCIHLPRC::pfnIsaSetIrq */
533static DECLCALLBACK(void) pdmRCPciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
534{
535 PDMDEV_ASSERT_DEVINS(pDevIns);
536 Log4(("pdmRCPciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
537 pdmRCIsaSetIrq(pDevIns->Internal.s.pVMRC, iIrq, iLevel);
538}
539
540
541/** @copydoc PDMPCIHLPRC::pfnIoApicSetIrq */
542static DECLCALLBACK(void) pdmRCPciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
543{
544 PDMDEV_ASSERT_DEVINS(pDevIns);
545 Log4(("pdmRCPciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
546 pdmRCIoApicSetIrq(pDevIns->Internal.s.pVMRC, iIrq, iLevel);
547}
548
549
550/** @copydoc PDMPCIHLPRC::pfnLock */
551static DECLCALLBACK(int) pdmRCPciHlp_Lock(PPDMDEVINS pDevIns, int rc)
552{
553 PDMDEV_ASSERT_DEVINS(pDevIns);
554 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
555}
556
557
558/** @copydoc PDMPCIHLPRC::pfnUnlock */
559static DECLCALLBACK(void) pdmRCPciHlp_Unlock(PPDMDEVINS pDevIns)
560{
561 PDMDEV_ASSERT_DEVINS(pDevIns);
562 pdmUnlock(pDevIns->Internal.s.pVMRC);
563}
564
565
566/**
567 * The Raw-Mode Context PCI Bus Helper Callbacks.
568 */
569extern DECLEXPORT(const PDMPCIHLPRC) g_pdmRCPciHlp =
570{
571 PDM_PCIHLPRC_VERSION,
572 pdmRCPciHlp_IsaSetIrq,
573 pdmRCPciHlp_IoApicSetIrq,
574 pdmRCPciHlp_Lock,
575 pdmRCPciHlp_Unlock,
576 PDM_PCIHLPRC_VERSION, /* the end */
577};
578
579/** @} */
580
581
582
583
584/** @name HPET RC Helpers
585 * @{
586 */
587
588/** @copydoc PDMHPETHLPRC::pfnLock */
589static DECLCALLBACK(int) pdmRCHpetHlp_Lock(PPDMDEVINS pDevIns, int rc)
590{
591 PDMDEV_ASSERT_DEVINS(pDevIns);
592 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
593}
594
595
596/** @copydoc PDMHPETHLPRC::pfnUnlock */
597static DECLCALLBACK(void) pdmRCHpetHlp_Unlock(PPDMDEVINS pDevIns)
598{
599 PDMDEV_ASSERT_DEVINS(pDevIns);
600 pdmUnlock(pDevIns->Internal.s.pVMRC);
601}
602
603
604/**
605 * The Raw-Mode Context HPET Helper Callbacks.
606 */
607extern DECLEXPORT(const PDMHPETHLPRC) g_pdmRCHpetHlp =
608{
609 PDM_HPETHLPRC_VERSION,
610 pdmRCHpetHlp_Lock,
611 pdmRCHpetHlp_Unlock,
612 PDM_HPETHLPRC_VERSION, /* the end */
613};
614
615/** @} */
616
617
618
619
620/**
621 * Sets an irq on the I/O APIC.
622 *
623 * @param pVM The VM handle.
624 * @param iIrq The irq.
625 * @param iLevel The new level.
626 */
627static void pdmRCIsaSetIrq(PVM pVM, int iIrq, int iLevel)
628{
629 if ( ( pVM->pdm.s.IoApic.pDevInsRC
630 || !pVM->pdm.s.IoApic.pDevInsR3)
631 && ( pVM->pdm.s.Pic.pDevInsRC
632 || !pVM->pdm.s.Pic.pDevInsR3))
633 {
634 pdmLock(pVM);
635 if (pVM->pdm.s.Pic.pDevInsRC)
636 pVM->pdm.s.Pic.pfnSetIrqRC(pVM->pdm.s.Pic.pDevInsRC, iIrq, iLevel);
637 if (pVM->pdm.s.IoApic.pDevInsRC)
638 pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel);
639 pdmUnlock(pVM);
640 }
641 else
642 {
643 /* queue for ring-3 execution. */
644 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
645 if (pTask)
646 {
647 pTask->enmOp = PDMDEVHLPTASKOP_ISA_SET_IRQ;
648 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
649 pTask->u.SetIRQ.iIrq = iIrq;
650 pTask->u.SetIRQ.iLevel = iLevel;
651
652 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
653 }
654 else
655 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
656 }
657}
658
659
660/**
661 * Sets an irq on the I/O APIC.
662 *
663 * @param pVM The VM handle.
664 * @param iIrq The irq.
665 * @param iLevel The new level.
666 */
667static void pdmRCIoApicSetIrq(PVM pVM, int iIrq, int iLevel)
668{
669 if (pVM->pdm.s.IoApic.pDevInsRC)
670 {
671 pdmLock(pVM);
672 pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel);
673 pdmUnlock(pVM);
674 }
675 else if (pVM->pdm.s.IoApic.pDevInsR3)
676 {
677 /* queue for ring-3 execution. */
678 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
679 if (pTask)
680 {
681 pTask->enmOp = PDMDEVHLPTASKOP_IOAPIC_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.pDevHlpQueueRC, &pTask->Core, 0);
687 }
688 else
689 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
690 }
691}
692
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