VirtualBox

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

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