VirtualBox

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

Last change on this file since 19360 was 19141, checked in by vboxsync, 16 years ago

Action flags breakup.
Fixed PGM saved state loading of 2.2.2 images.
Reduced hacks in PATM state loading (fixups).

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