VirtualBox

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

Last change on this file since 18068 was 17534, checked in by vboxsync, 16 years ago

PGM: Made PGMPhysRead/Write return VERR_PGM_PHYS_WR_HIT_HANDLER when encountering a handler in R0 and RC. Adjusted PGMPhysReadGCPtr and PGMPhysWriteGCPtr to not waste time on setting A and D bits if they are already set.

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