VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMRC/PDMRCDevice.cpp@ 37410

Last change on this file since 37410 was 37410, checked in by vboxsync, 13 years ago

VMM,SUPDrv: Created DBGFTrace.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 26.7 KB
Line 
1/* $Id: PDMRCDevice.cpp 37410 2011-06-10 15:11:40Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, RC Device parts.
4 */
5
6/*
7 * Copyright (C) 2006-2011 Oracle Corporation
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
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_PDM_DEVICE
23#include "PDMInternal.h"
24#include <VBox/vmm/pdm.h>
25#include <VBox/vmm/pgm.h>
26#include <VBox/vmm/mm.h>
27#include <VBox/vmm/vm.h>
28#include <VBox/vmm/vmm.h>
29#include <VBox/vmm/patm.h>
30
31#include <VBox/log.h>
32#include <VBox/err.h>
33#include <iprt/asm.h>
34#include <iprt/assert.h>
35#include <iprt/string.h>
36
37
38/*******************************************************************************
39* Global Variables *
40*******************************************************************************/
41RT_C_DECLS_BEGIN
42extern DECLEXPORT(const PDMDEVHLPRC) g_pdmRCDevHlp;
43extern DECLEXPORT(const PDMPICHLPRC) g_pdmRCPicHlp;
44extern DECLEXPORT(const PDMAPICHLPRC) g_pdmRCApicHlp;
45extern DECLEXPORT(const PDMIOAPICHLPRC) g_pdmRCIoApicHlp;
46extern DECLEXPORT(const PDMPCIHLPRC) g_pdmRCPciHlp;
47extern DECLEXPORT(const PDMHPETHLPRC) g_pdmRCHpetHlp;
48extern DECLEXPORT(const PDMDRVHLPRC) g_pdmRCDrvHlp;
49/** @todo missing PDMPCIRAWHLPRC */
50RT_C_DECLS_END
51
52
53/*******************************************************************************
54* Internal Functions *
55*******************************************************************************/
56static void pdmRCIsaSetIrq(PVM pVM, int iIrq, int iLevel);
57static void pdmRCIoApicSetIrq(PVM pVM, int iIrq, int iLevel);
58static void pdmRCIoApicSendMsi(PVM pVM, RTGCPHYS GCAddr, uint32_t uValue);
59
60/** @name Raw-Mode Context Device Helpers
61 * @{
62 */
63
64/** @interface_method_impl{PDMDEVHLPRC,pfnPCISetIrq} */
65static DECLCALLBACK(void) pdmRCDevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
66{
67 PDMDEV_ASSERT_DEVINS(pDevIns);
68 LogFlow(("pdmRCDevHlp_PCISetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
69
70 PVM pVM = pDevIns->Internal.s.pVMRC;
71 PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceRC;
72 PPDMPCIBUS pPciBus = pDevIns->Internal.s.pPciBusRC;
73 if ( pPciDev
74 && pPciBus
75 && pPciBus->pDevInsRC)
76 {
77 pdmLock(pVM);
78 pPciBus->pfnSetIrqRC(pPciBus->pDevInsRC, pPciDev, iIrq, iLevel);
79 pdmUnlock(pVM);
80 }
81 else
82 {
83 /* queue for ring-3 execution. */
84 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
85 if (pTask)
86 {
87 pTask->enmOp = PDMDEVHLPTASKOP_PCI_SET_IRQ;
88 pTask->pDevInsR3 = PDMDEVINS_2_R3PTR(pDevIns);
89 pTask->u.SetIRQ.iIrq = iIrq;
90 pTask->u.SetIRQ.iLevel = iLevel;
91
92 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
93 }
94 else
95 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
96 }
97
98 LogFlow(("pdmRCDevHlp_PCISetIrq: caller=%p/%d: returns void\n", pDevIns, pDevIns->iInstance));
99}
100
101
102/** @interface_method_impl{PDMDRVHLPRC,pfnPCISetIrq} */
103static DECLCALLBACK(void) pdmRCDevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
104{
105 PDMDEV_ASSERT_DEVINS(pDevIns);
106 LogFlow(("pdmRCDevHlp_ISASetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
107
108 pdmRCIsaSetIrq(pDevIns->Internal.s.pVMRC, iIrq, iLevel);
109
110 LogFlow(("pdmRCDevHlp_ISASetIrq: caller=%p/%d: returns void\n", pDevIns, pDevIns->iInstance));
111}
112
113
114/** @interface_method_impl{PDMDEVHLPRC,pfnPhysRead} */
115static DECLCALLBACK(int) pdmRCDevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
116{
117 PDMDEV_ASSERT_DEVINS(pDevIns);
118 LogFlow(("pdmRCDevHlp_PhysRead: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
119 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
120
121 int rc = PGMPhysRead(pDevIns->Internal.s.pVMRC, GCPhys, pvBuf, cbRead);
122 AssertRC(rc); /** @todo track down the users for this bugger. */
123
124 Log(("pdmRCDevHlp_PhysRead: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, rc));
125 return rc;
126}
127
128
129/** @interface_method_impl{PDMDEVHLPRC,pfnPhysWrite} */
130static DECLCALLBACK(int) pdmRCDevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
131{
132 PDMDEV_ASSERT_DEVINS(pDevIns);
133 LogFlow(("pdmRCDevHlp_PhysWrite: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
134 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
135
136 int rc = PGMPhysWrite(pDevIns->Internal.s.pVMRC, GCPhys, pvBuf, cbWrite);
137 AssertRC(rc); /** @todo track down the users for this bugger. */
138
139 Log(("pdmRCDevHlp_PhysWrite: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, rc));
140 return rc;
141}
142
143
144/** @interface_method_impl{PDMDEVHLPRC,pfnA20IsEnabled} */
145static DECLCALLBACK(bool) pdmRCDevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
146{
147 PDMDEV_ASSERT_DEVINS(pDevIns);
148 LogFlow(("pdmRCDevHlp_A20IsEnabled: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
149
150 bool fEnabled = PGMPhysIsA20Enabled(VMMGetCpu0(pDevIns->Internal.s.pVMRC));
151
152 Log(("pdmRCDevHlp_A20IsEnabled: caller=%p/%d: returns %RTbool\n", pDevIns, pDevIns->iInstance, fEnabled));
153 return fEnabled;
154}
155
156
157/** @interface_method_impl{PDMDEVHLPRC,pfnVMState} */
158static DECLCALLBACK(VMSTATE) pdmRCDevHlp_VMState(PPDMDEVINS pDevIns)
159{
160 PDMDEV_ASSERT_DEVINS(pDevIns);
161
162 VMSTATE enmVMState = pDevIns->Internal.s.pVMRC->enmVMState;
163
164 LogFlow(("pdmRCDevHlp_VMState: caller=%p/%d: returns %d\n", pDevIns, pDevIns->iInstance, enmVMState));
165 return enmVMState;
166}
167
168
169/** @interface_method_impl{PDMDEVHLPRC,pfnVMSetError} */
170static DECLCALLBACK(int) pdmRCDevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
171{
172 PDMDEV_ASSERT_DEVINS(pDevIns);
173 va_list args;
174 va_start(args, pszFormat);
175 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
176 va_end(args);
177 return rc;
178}
179
180
181/** @interface_method_impl{PDMDEVHLPRC,pfnVMSetErrorV} */
182static DECLCALLBACK(int) pdmRCDevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
183{
184 PDMDEV_ASSERT_DEVINS(pDevIns);
185 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
186 return rc;
187}
188
189
190/** @interface_method_impl{PDMDEVHLPRC,pfnVMSetRuntimeError} */
191static DECLCALLBACK(int) pdmRCDevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
192{
193 PDMDEV_ASSERT_DEVINS(pDevIns);
194 va_list va;
195 va_start(va, pszFormat);
196 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
197 va_end(va);
198 return rc;
199}
200
201
202/** @interface_method_impl{PDMDEVHLPRC,pfnVMSetErrorV} */
203static DECLCALLBACK(int) pdmRCDevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
204{
205 PDMDEV_ASSERT_DEVINS(pDevIns);
206 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
207 return rc;
208}
209
210
211/** @interface_method_impl{PDMDEVHLPRC,pfnPATMSetMMIOPatchInfo} */
212static DECLCALLBACK(int) pdmRCDevHlp_PATMSetMMIOPatchInfo(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPTR pCachedData)
213{
214 PDMDEV_ASSERT_DEVINS(pDevIns);
215 LogFlow(("pdmRCDevHlp_PATMSetMMIOPatchInfo: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
216
217 return PATMSetMMIOPatchInfo(pDevIns->Internal.s.pVMRC, GCPhys, (RTRCPTR)(uintptr_t)pCachedData);
218}
219
220
221/** @interface_method_impl{PDMDEVHLPRC,pfnGetVM} */
222static DECLCALLBACK(PVM) pdmRCDevHlp_GetVM(PPDMDEVINS pDevIns)
223{
224 PDMDEV_ASSERT_DEVINS(pDevIns);
225 LogFlow(("pdmRCDevHlp_GetVM: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
226 return pDevIns->Internal.s.pVMRC;
227}
228
229
230/** @interface_method_impl{PDMDEVHLPRC,pfnGetVMCPU} */
231static DECLCALLBACK(PVMCPU) pdmRCDevHlp_GetVMCPU(PPDMDEVINS pDevIns)
232{
233 PDMDEV_ASSERT_DEVINS(pDevIns);
234 LogFlow(("pdmRCDevHlp_GetVMCPU: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
235 return VMMGetCpu(pDevIns->Internal.s.pVMRC);
236}
237
238
239/** @interface_method_impl{PDMDEVHLPRC,pfnTMTimeVirtGet} */
240static DECLCALLBACK(uint64_t) pdmRCDevHlp_TMTimeVirtGet(PPDMDEVINS pDevIns)
241{
242 PDMDEV_ASSERT_DEVINS(pDevIns);
243 LogFlow(("pdmRCDevHlp_TMTimeVirtGet: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
244 return TMVirtualGet(pDevIns->Internal.s.pVMRC);
245}
246
247
248/** @interface_method_impl{PDMDEVHLPRC,pfnTMTimeVirtGetFreq} */
249static DECLCALLBACK(uint64_t) pdmRCDevHlp_TMTimeVirtGetFreq(PPDMDEVINS pDevIns)
250{
251 PDMDEV_ASSERT_DEVINS(pDevIns);
252 LogFlow(("pdmRCDevHlp_TMTimeVirtGetFreq: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
253 return TMVirtualGetFreq(pDevIns->Internal.s.pVMRC);
254}
255
256
257/** @interface_method_impl{PDMDEVHLPRC,pfnTMTimeVirtGetNano} */
258static DECLCALLBACK(uint64_t) pdmRCDevHlp_TMTimeVirtGetNano(PPDMDEVINS pDevIns)
259{
260 PDMDEV_ASSERT_DEVINS(pDevIns);
261 LogFlow(("pdmRCDevHlp_TMTimeVirtGetNano: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
262 return TMVirtualToNano(pDevIns->Internal.s.pVMRC, TMVirtualGet(pDevIns->Internal.s.pVMRC));
263}
264
265
266/** @interface_method_impl{PDMDEVHLPRC,pfnDBGFTraceBuf} */
267static DECLCALLBACK(RTTRACEBUF) pdmRCDevHlp_DBGFTraceBuf(PPDMDEVINS pDevIns)
268{
269 PDMDEV_ASSERT_DEVINS(pDevIns);
270 RTTRACEBUF hTraceBuf = pDevIns->Internal.s.pVMRC->hTraceBufRC;
271 LogFlow(("pdmRCDevHlp_DBGFTraceBuf: caller='%p'/%d: returns %p\n", pDevIns, pDevIns->iInstance, hTraceBuf));
272 return hTraceBuf;
273}
274
275
276/**
277 * The Raw-Mode Context Device Helper Callbacks.
278 */
279extern DECLEXPORT(const PDMDEVHLPRC) g_pdmRCDevHlp =
280{
281 PDM_DEVHLPRC_VERSION,
282 pdmRCDevHlp_PCISetIrq,
283 pdmRCDevHlp_ISASetIrq,
284 pdmRCDevHlp_PhysRead,
285 pdmRCDevHlp_PhysWrite,
286 pdmRCDevHlp_A20IsEnabled,
287 pdmRCDevHlp_VMState,
288 pdmRCDevHlp_VMSetError,
289 pdmRCDevHlp_VMSetErrorV,
290 pdmRCDevHlp_VMSetRuntimeError,
291 pdmRCDevHlp_VMSetRuntimeErrorV,
292 pdmRCDevHlp_PATMSetMMIOPatchInfo,
293 pdmRCDevHlp_GetVM,
294 pdmRCDevHlp_GetVMCPU,
295 pdmRCDevHlp_TMTimeVirtGet,
296 pdmRCDevHlp_TMTimeVirtGetFreq,
297 pdmRCDevHlp_TMTimeVirtGetNano,
298 pdmRCDevHlp_DBGFTraceBuf,
299 PDM_DEVHLPRC_VERSION
300};
301
302/** @} */
303
304
305
306
307/** @name PIC RC Helpers
308 * @{
309 */
310
311/** @interface_method_impl{PDMPICHLPGC,pfnSetInterruptFF} */
312static DECLCALLBACK(void) pdmRCPicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
313{
314 PDMDEV_ASSERT_DEVINS(pDevIns);
315 PVM pVM = pDevIns->Internal.s.pVMRC;
316
317 if (pVM->pdm.s.Apic.pfnLocalInterruptRC)
318 {
319 LogFlow(("pdmRCPicHlp_SetInterruptFF: caller='%p'/%d: Setting local interrupt on LAPIC\n",
320 pDevIns, pDevIns->iInstance));
321 /* Raise the LAPIC's LINT0 line instead of signaling the CPU directly. */
322 pVM->pdm.s.Apic.pfnLocalInterruptRC(pVM->pdm.s.Apic.pDevInsRC, 0, 1);
323 return;
324 }
325
326 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
327
328 LogFlow(("pdmRCPicHlp_SetInterruptFF: caller=%p/%d: VMMCPU_FF_INTERRUPT_PIC %d -> 1\n",
329 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_PIC)));
330
331 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC);
332}
333
334
335/** @interface_method_impl{PDMPICHLPGC,pfnClearInterruptFF} */
336static DECLCALLBACK(void) pdmRCPicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
337{
338 PDMDEV_ASSERT_DEVINS(pDevIns);
339 PVM pVM = pDevIns->Internal.s.CTX_SUFF(pVM);
340
341 if (pVM->pdm.s.Apic.pfnLocalInterruptRC)
342 {
343 /* Raise the LAPIC's LINT0 line instead of signaling the CPU directly. */
344 LogFlow(("pdmRCPicHlp_ClearInterruptFF: caller='%s'/%d: Clearing local interrupt on LAPIC\n",
345 pDevIns, pDevIns->iInstance));
346 /* Lower the LAPIC's LINT0 line instead of signaling the CPU directly. */
347 pVM->pdm.s.Apic.pfnLocalInterruptRC(pVM->pdm.s.Apic.pDevInsRC, 0, 0);
348 return;
349 }
350
351 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
352
353 LogFlow(("pdmRCPicHlp_ClearInterruptFF: caller=%p/%d: VMCPU_FF_INTERRUPT_PIC %d -> 0\n",
354 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_PIC)));
355
356 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
357}
358
359
360/** @interface_method_impl{PDMPICHLPGC,pfnLock} */
361static DECLCALLBACK(int) pdmRCPicHlp_Lock(PPDMDEVINS pDevIns, int rc)
362{
363 PDMDEV_ASSERT_DEVINS(pDevIns);
364 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
365}
366
367
368/** @interface_method_impl{PDMPICHLPGC,pfnUnlock} */
369static DECLCALLBACK(void) pdmRCPicHlp_Unlock(PPDMDEVINS pDevIns)
370{
371 PDMDEV_ASSERT_DEVINS(pDevIns);
372 pdmUnlock(pDevIns->Internal.s.pVMRC);
373}
374
375
376/**
377 * The Raw-Mode Context PIC Helper Callbacks.
378 */
379extern DECLEXPORT(const PDMPICHLPRC) g_pdmRCPicHlp =
380{
381 PDM_PICHLPRC_VERSION,
382 pdmRCPicHlp_SetInterruptFF,
383 pdmRCPicHlp_ClearInterruptFF,
384 pdmRCPicHlp_Lock,
385 pdmRCPicHlp_Unlock,
386 PDM_PICHLPRC_VERSION
387};
388
389/** @} */
390
391
392
393
394/** @name APIC RC Helpers
395 * @{
396 */
397
398/** @interface_method_impl{PDMAPICHLPRC,pfnSetInterruptFF} */
399static DECLCALLBACK(void) pdmRCApicHlp_SetInterruptFF(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu)
400{
401 PDMDEV_ASSERT_DEVINS(pDevIns);
402 PVM pVM = pDevIns->Internal.s.pVMRC;
403 PVMCPU pVCpu = &pVM->aCpus[idCpu];
404
405 AssertReturnVoid(idCpu < pVM->cCpus);
406
407 LogFlow(("pdmRCApicHlp_SetInterruptFF: caller=%p/%d: VM_FF_INTERRUPT %d -> 1\n",
408 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_APIC)));
409 switch (enmType)
410 {
411 case PDMAPICIRQ_HARDWARE:
412 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC);
413 break;
414 case PDMAPICIRQ_NMI:
415 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI);
416 break;
417 case PDMAPICIRQ_SMI:
418 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_SMI);
419 break;
420 case PDMAPICIRQ_EXTINT:
421 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC);
422 break;
423 default:
424 AssertMsgFailed(("enmType=%d\n", enmType));
425 break;
426 }
427}
428
429
430/** @interface_method_impl{PDMAPICHLPRC,pfnClearInterruptFF} */
431static DECLCALLBACK(void) pdmRCApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu)
432{
433 PDMDEV_ASSERT_DEVINS(pDevIns);
434 PVM pVM = pDevIns->Internal.s.pVMRC;
435 PVMCPU pVCpu = &pVM->aCpus[idCpu];
436
437 AssertReturnVoid(idCpu < pVM->cCpus);
438
439 LogFlow(("pdmRCApicHlp_ClearInterruptFF: caller=%p/%d: VM_FF_INTERRUPT %d -> 0\n",
440 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_APIC)));
441
442 /* Note: NMI/SMI can't be cleared. */
443 switch (enmType)
444 {
445 case PDMAPICIRQ_HARDWARE:
446 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_APIC);
447 break;
448 case PDMAPICIRQ_EXTINT:
449 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
450 break;
451 default:
452 AssertMsgFailed(("enmType=%d\n", enmType));
453 break;
454 }
455}
456
457
458/** @interface_method_impl{PDMAPICHLPRC,pfnChangeFeature} */
459static DECLCALLBACK(void) pdmRCApicHlp_ChangeFeature(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion)
460{
461 PDMDEV_ASSERT_DEVINS(pDevIns);
462 LogFlow(("pdmRCApicHlp_ChangeFeature: caller=%p/%d: version=%d\n", pDevIns, pDevIns->iInstance, (int)enmVersion));
463 switch (enmVersion)
464 {
465 case PDMAPICVERSION_NONE:
466 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_APIC);
467 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_X2APIC);
468 break;
469 case PDMAPICVERSION_APIC:
470 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_APIC);
471 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_X2APIC);
472 break;
473 case PDMAPICVERSION_X2APIC:
474 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_X2APIC);
475 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_APIC);
476 break;
477 default:
478 AssertMsgFailed(("Unknown APIC version: %d\n", (int)enmVersion));
479 }
480}
481
482
483/** @interface_method_impl{PDMAPICHLPRC,pfnLock} */
484static DECLCALLBACK(int) pdmRCApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
485{
486 PDMDEV_ASSERT_DEVINS(pDevIns);
487 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
488}
489
490
491/** @interface_method_impl{PDMAPICHLPRC,pfnUnlock} */
492static DECLCALLBACK(void) pdmRCApicHlp_Unlock(PPDMDEVINS pDevIns)
493{
494 PDMDEV_ASSERT_DEVINS(pDevIns);
495 pdmUnlock(pDevIns->Internal.s.pVMRC);
496}
497
498
499/** @interface_method_impl{PDMAPICHLPRC,pfnGetCpuId} */
500static DECLCALLBACK(VMCPUID) pdmRCApicHlp_GetCpuId(PPDMDEVINS pDevIns)
501{
502 PDMDEV_ASSERT_DEVINS(pDevIns);
503 return VMMGetCpuId(pDevIns->Internal.s.pVMRC);
504}
505
506
507/**
508 * The Raw-Mode Context APIC Helper Callbacks.
509 */
510extern DECLEXPORT(const PDMAPICHLPRC) g_pdmRCApicHlp =
511{
512 PDM_APICHLPRC_VERSION,
513 pdmRCApicHlp_SetInterruptFF,
514 pdmRCApicHlp_ClearInterruptFF,
515 pdmRCApicHlp_ChangeFeature,
516 pdmRCApicHlp_Lock,
517 pdmRCApicHlp_Unlock,
518 pdmRCApicHlp_GetCpuId,
519 PDM_APICHLPRC_VERSION
520};
521
522/** @} */
523
524
525
526
527/** @name I/O APIC RC Helpers
528 * @{
529 */
530
531/** @interface_method_impl{PDMIOAPICHLPRC,pfnApicBusDeliver} */
532static DECLCALLBACK(int) pdmRCIoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
533 uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode)
534{
535 PDMDEV_ASSERT_DEVINS(pDevIns);
536 PVM pVM = pDevIns->Internal.s.pVMRC;
537 LogFlow(("pdmRCIoApicHlp_ApicBusDeliver: caller=%p/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8\n",
538 pDevIns, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode));
539 if (pVM->pdm.s.Apic.pfnBusDeliverRC)
540 return pVM->pdm.s.Apic.pfnBusDeliverRC(pVM->pdm.s.Apic.pDevInsRC, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode);
541 return VINF_SUCCESS;
542}
543
544
545/** @interface_method_impl{PDMIOAPICHLPRC,pfnLock} */
546static DECLCALLBACK(int) pdmRCIoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
547{
548 PDMDEV_ASSERT_DEVINS(pDevIns);
549 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
550}
551
552
553/** @interface_method_impl{PDMIOAPICHLPRC,pfnUnlock} */
554static DECLCALLBACK(void) pdmRCIoApicHlp_Unlock(PPDMDEVINS pDevIns)
555{
556 PDMDEV_ASSERT_DEVINS(pDevIns);
557 pdmUnlock(pDevIns->Internal.s.pVMRC);
558}
559
560
561/**
562 * The Raw-Mode Context I/O APIC Helper Callbacks.
563 */
564extern DECLEXPORT(const PDMIOAPICHLPRC) g_pdmRCIoApicHlp =
565{
566 PDM_IOAPICHLPRC_VERSION,
567 pdmRCIoApicHlp_ApicBusDeliver,
568 pdmRCIoApicHlp_Lock,
569 pdmRCIoApicHlp_Unlock,
570 PDM_IOAPICHLPRC_VERSION
571};
572
573/** @} */
574
575
576
577
578/** @name PCI Bus RC Helpers
579 * @{
580 */
581
582/** @interface_method_impl{PDMPCIHLPRC,pfnIsaSetIrq} */
583static DECLCALLBACK(void) pdmRCPciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
584{
585 PDMDEV_ASSERT_DEVINS(pDevIns);
586 Log4(("pdmRCPciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
587 pdmRCIsaSetIrq(pDevIns->Internal.s.pVMRC, iIrq, iLevel);
588}
589
590
591/** @interface_method_impl{PDMPCIHLPRC,pfnIoApicSetIrq} */
592static DECLCALLBACK(void) pdmRCPciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
593{
594 PDMDEV_ASSERT_DEVINS(pDevIns);
595 Log4(("pdmRCPciHlp_IoApicSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
596 pdmRCIoApicSetIrq(pDevIns->Internal.s.pVMRC, iIrq, iLevel);
597}
598
599/** @interface_method_impl{PDMPCIHLPRC,pfnIoApicSendMsi} */
600static DECLCALLBACK(void) pdmRCPciHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCAddr, uint32_t uValue)
601{
602 PDMDEV_ASSERT_DEVINS(pDevIns);
603 Log4(("pdmRCPciHlp_IoApicSendMsi: Address=%p Value=%d\n", GCAddr, uValue));
604 pdmRCIoApicSendMsi(pDevIns->Internal.s.pVMRC, GCAddr, uValue);
605}
606
607
608/** @interface_method_impl{PDMPCIHLPRC,pfnLock} */
609static DECLCALLBACK(int) pdmRCPciHlp_Lock(PPDMDEVINS pDevIns, int rc)
610{
611 PDMDEV_ASSERT_DEVINS(pDevIns);
612 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
613}
614
615
616/** @interface_method_impl{PDMPCIHLPRC,pfnUnlock} */
617static DECLCALLBACK(void) pdmRCPciHlp_Unlock(PPDMDEVINS pDevIns)
618{
619 PDMDEV_ASSERT_DEVINS(pDevIns);
620 pdmUnlock(pDevIns->Internal.s.pVMRC);
621}
622
623
624/**
625 * The Raw-Mode Context PCI Bus Helper Callbacks.
626 */
627extern DECLEXPORT(const PDMPCIHLPRC) g_pdmRCPciHlp =
628{
629 PDM_PCIHLPRC_VERSION,
630 pdmRCPciHlp_IsaSetIrq,
631 pdmRCPciHlp_IoApicSetIrq,
632 pdmRCPciHlp_IoApicSendMsi,
633 pdmRCPciHlp_Lock,
634 pdmRCPciHlp_Unlock,
635 PDM_PCIHLPRC_VERSION, /* the end */
636};
637
638/** @} */
639
640
641
642
643/** @name HPET RC Helpers
644 * @{
645 */
646
647
648/**
649 * The Raw-Mode Context HPET Helper Callbacks.
650 */
651extern DECLEXPORT(const PDMHPETHLPRC) g_pdmRCHpetHlp =
652{
653 PDM_HPETHLPRC_VERSION,
654 PDM_HPETHLPRC_VERSION, /* the end */
655};
656
657/** @} */
658
659
660
661
662/** @name Raw-Mode Context Driver Helpers
663 * @{
664 */
665
666/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetError} */
667static DECLCALLBACK(int) pdmRCDrvHlp_VMSetError(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
668{
669 PDMDRV_ASSERT_DRVINS(pDrvIns);
670 va_list args;
671 va_start(args, pszFormat);
672 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
673 va_end(args);
674 return rc;
675}
676
677
678/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetErrorV} */
679static DECLCALLBACK(int) pdmRCDrvHlp_VMSetErrorV(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
680{
681 PDMDRV_ASSERT_DRVINS(pDrvIns);
682 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
683 return rc;
684}
685
686
687/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetRuntimeError} */
688static DECLCALLBACK(int) pdmRCDrvHlp_VMSetRuntimeError(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
689{
690 PDMDRV_ASSERT_DRVINS(pDrvIns);
691 va_list va;
692 va_start(va, pszFormat);
693 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
694 va_end(va);
695 return rc;
696}
697
698
699/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetErrorV} */
700static DECLCALLBACK(int) pdmRCDrvHlp_VMSetRuntimeErrorV(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
701{
702 PDMDRV_ASSERT_DRVINS(pDrvIns);
703 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
704 return rc;
705}
706
707
708/** @interface_method_impl{PDMDRVHLPRC,pfnAssertEMT} */
709static DECLCALLBACK(bool) pdmRCDrvHlp_AssertEMT(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
710{
711 PDMDRV_ASSERT_DRVINS(pDrvIns);
712 if (VM_IS_EMT(pDrvIns->Internal.s.pVMRC))
713 return true;
714
715 RTAssertMsg1Weak("AssertEMT", iLine, pszFile, pszFunction);
716 RTAssertPanic();
717 return false;
718}
719
720
721/** @interface_method_impl{PDMDRVHLPRC,pfnAssertOther} */
722static DECLCALLBACK(bool) pdmRCDrvHlp_AssertOther(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
723{
724 PDMDRV_ASSERT_DRVINS(pDrvIns);
725 if (!VM_IS_EMT(pDrvIns->Internal.s.pVMRC))
726 return true;
727
728 /* Note: While we don't have any other threads but EMT(0) in RC, might
729 still have drive code compiled in which it shouldn't execute. */
730 RTAssertMsg1Weak("AssertOther", iLine, pszFile, pszFunction);
731 RTAssertPanic();
732 return false;
733}
734
735
736/** @interface_method_impl{PDMDRVHLPRC,pfnFTSetCheckpoint} */
737static DECLCALLBACK(int) pdmRCDrvHlp_FTSetCheckpoint(PPDMDRVINS pDrvIns, FTMCHECKPOINTTYPE enmType)
738{
739 PDMDRV_ASSERT_DRVINS(pDrvIns);
740 return FTMSetCheckpoint(pDrvIns->Internal.s.pVMRC, enmType);
741}
742
743
744/**
745 * The Raw-Mode Context Driver Helper Callbacks.
746 */
747extern DECLEXPORT(const PDMDRVHLPRC) g_pdmRCDrvHlp =
748{
749 PDM_DRVHLPRC_VERSION,
750 pdmRCDrvHlp_VMSetError,
751 pdmRCDrvHlp_VMSetErrorV,
752 pdmRCDrvHlp_VMSetRuntimeError,
753 pdmRCDrvHlp_VMSetRuntimeErrorV,
754 pdmRCDrvHlp_AssertEMT,
755 pdmRCDrvHlp_AssertOther,
756 pdmRCDrvHlp_FTSetCheckpoint,
757 PDM_DRVHLPRC_VERSION
758};
759
760/** @} */
761
762
763
764
765/**
766 * Sets an irq on the I/O APIC.
767 *
768 * @param pVM The VM handle.
769 * @param iIrq The irq.
770 * @param iLevel The new level.
771 */
772static void pdmRCIsaSetIrq(PVM pVM, int iIrq, int iLevel)
773{
774 if ( ( pVM->pdm.s.IoApic.pDevInsRC
775 || !pVM->pdm.s.IoApic.pDevInsR3)
776 && ( pVM->pdm.s.Pic.pDevInsRC
777 || !pVM->pdm.s.Pic.pDevInsR3))
778 {
779 pdmLock(pVM);
780 if (pVM->pdm.s.Pic.pDevInsRC)
781 pVM->pdm.s.Pic.pfnSetIrqRC(pVM->pdm.s.Pic.pDevInsRC, iIrq, iLevel);
782 if (pVM->pdm.s.IoApic.pDevInsRC)
783 pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel);
784 pdmUnlock(pVM);
785 }
786 else
787 {
788 /* queue for ring-3 execution. */
789 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
790 if (pTask)
791 {
792 pTask->enmOp = PDMDEVHLPTASKOP_ISA_SET_IRQ;
793 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
794 pTask->u.SetIRQ.iIrq = iIrq;
795 pTask->u.SetIRQ.iLevel = iLevel;
796
797 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
798 }
799 else
800 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
801 }
802}
803
804
805/**
806 * Sets an irq on the I/O APIC.
807 *
808 * @param pVM The VM handle.
809 * @param iIrq The irq.
810 * @param iLevel The new level.
811 */
812static void pdmRCIoApicSetIrq(PVM pVM, int iIrq, int iLevel)
813{
814 if (pVM->pdm.s.IoApic.pDevInsRC)
815 {
816 pdmLock(pVM);
817 pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel);
818 pdmUnlock(pVM);
819 }
820 else if (pVM->pdm.s.IoApic.pDevInsR3)
821 {
822 /* queue for ring-3 execution. */
823 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
824 if (pTask)
825 {
826 pTask->enmOp = PDMDEVHLPTASKOP_IOAPIC_SET_IRQ;
827 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
828 pTask->u.SetIRQ.iIrq = iIrq;
829 pTask->u.SetIRQ.iLevel = iLevel;
830
831 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
832 }
833 else
834 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
835 }
836}
837
838
839/**
840 * Sends an MSI to I/O APIC.
841 *
842 * @param pVM The VM handle.
843 * @param GCAddr Address of the message.
844 * @param uValue Value of the message.
845 */
846static void pdmRCIoApicSendMsi(PVM pVM, RTGCPHYS GCAddr, uint32_t uValue)
847{
848 if (pVM->pdm.s.IoApic.pDevInsRC)
849 {
850 pdmLock(pVM);
851 pVM->pdm.s.IoApic.pfnSendMsiRC(pVM->pdm.s.IoApic.pDevInsRC, GCAddr, uValue);
852 pdmUnlock(pVM);
853 }
854}
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