VirtualBox

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

Last change on this file since 13796 was 13412, checked in by vboxsync, 16 years ago

spaces. sigh.

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