VirtualBox

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

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

VMM: PDM infrastructure for HPET

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