VirtualBox

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

Last change on this file since 41783 was 41783, checked in by vboxsync, 12 years ago

Doxygen, comment typos.

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