VirtualBox

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

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

Working on tracking IRQs for tracing and logging purposes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 28.0 KB
Line 
1/* $Id: PDMRCDevice.cpp 40907 2012-04-13 20:50:14Z 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,pfnChangeFeature} */
495static DECLCALLBACK(void) pdmRCApicHlp_ChangeFeature(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion)
496{
497 PDMDEV_ASSERT_DEVINS(pDevIns);
498 LogFlow(("pdmRCApicHlp_ChangeFeature: caller=%p/%d: version=%d\n", pDevIns, pDevIns->iInstance, (int)enmVersion));
499 switch (enmVersion)
500 {
501 case PDMAPICVERSION_NONE:
502 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_APIC);
503 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_X2APIC);
504 break;
505 case PDMAPICVERSION_APIC:
506 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_APIC);
507 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_X2APIC);
508 break;
509 case PDMAPICVERSION_X2APIC:
510 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_X2APIC);
511 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_APIC);
512 break;
513 default:
514 AssertMsgFailed(("Unknown APIC version: %d\n", (int)enmVersion));
515 }
516}
517
518
519/** @interface_method_impl{PDMAPICHLPRC,pfnLock} */
520static DECLCALLBACK(int) pdmRCApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
521{
522 PDMDEV_ASSERT_DEVINS(pDevIns);
523 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
524}
525
526
527/** @interface_method_impl{PDMAPICHLPRC,pfnUnlock} */
528static DECLCALLBACK(void) pdmRCApicHlp_Unlock(PPDMDEVINS pDevIns)
529{
530 PDMDEV_ASSERT_DEVINS(pDevIns);
531 pdmUnlock(pDevIns->Internal.s.pVMRC);
532}
533
534
535/** @interface_method_impl{PDMAPICHLPRC,pfnGetCpuId} */
536static DECLCALLBACK(VMCPUID) pdmRCApicHlp_GetCpuId(PPDMDEVINS pDevIns)
537{
538 PDMDEV_ASSERT_DEVINS(pDevIns);
539 return VMMGetCpuId(pDevIns->Internal.s.pVMRC);
540}
541
542
543/**
544 * The Raw-Mode Context APIC Helper Callbacks.
545 */
546extern DECLEXPORT(const PDMAPICHLPRC) g_pdmRCApicHlp =
547{
548 PDM_APICHLPRC_VERSION,
549 pdmRCApicHlp_SetInterruptFF,
550 pdmRCApicHlp_ClearInterruptFF,
551 pdmRCApicHlp_ChangeFeature,
552 pdmRCApicHlp_Lock,
553 pdmRCApicHlp_Unlock,
554 pdmRCApicHlp_GetCpuId,
555 PDM_APICHLPRC_VERSION
556};
557
558/** @} */
559
560
561
562
563/** @name I/O APIC RC Helpers
564 * @{
565 */
566
567/** @interface_method_impl{PDMIOAPICHLPRC,pfnApicBusDeliver} */
568static DECLCALLBACK(int) pdmRCIoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
569 uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc)
570{
571 PDMDEV_ASSERT_DEVINS(pDevIns);
572 PVM pVM = pDevIns->Internal.s.pVMRC;
573 LogFlow(("pdmRCIoApicHlp_ApicBusDeliver: caller=%p/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8 uTagSrc=%#x\n",
574 pDevIns, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode, uTagSrc));
575 Assert(pVM->pdm.s.Apic.pDevInsRC);
576 if (pVM->pdm.s.Apic.pfnBusDeliverRC)
577 return pVM->pdm.s.Apic.pfnBusDeliverRC(pVM->pdm.s.Apic.pDevInsRC, u8Dest, u8DestMode, u8DeliveryMode, iVector,
578 u8Polarity, u8TriggerMode, uTagSrc);
579 return VINF_SUCCESS;
580}
581
582
583/** @interface_method_impl{PDMIOAPICHLPRC,pfnLock} */
584static DECLCALLBACK(int) pdmRCIoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
585{
586 PDMDEV_ASSERT_DEVINS(pDevIns);
587 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
588}
589
590
591/** @interface_method_impl{PDMIOAPICHLPRC,pfnUnlock} */
592static DECLCALLBACK(void) pdmRCIoApicHlp_Unlock(PPDMDEVINS pDevIns)
593{
594 PDMDEV_ASSERT_DEVINS(pDevIns);
595 pdmUnlock(pDevIns->Internal.s.pVMRC);
596}
597
598
599/**
600 * The Raw-Mode Context I/O APIC Helper Callbacks.
601 */
602extern DECLEXPORT(const PDMIOAPICHLPRC) g_pdmRCIoApicHlp =
603{
604 PDM_IOAPICHLPRC_VERSION,
605 pdmRCIoApicHlp_ApicBusDeliver,
606 pdmRCIoApicHlp_Lock,
607 pdmRCIoApicHlp_Unlock,
608 PDM_IOAPICHLPRC_VERSION
609};
610
611/** @} */
612
613
614
615
616/** @name PCI Bus RC Helpers
617 * @{
618 */
619
620/** @interface_method_impl{PDMPCIHLPRC,pfnIsaSetIrq} */
621static DECLCALLBACK(void) pdmRCPciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
622{
623 PDMDEV_ASSERT_DEVINS(pDevIns);
624 Log4(("pdmRCPciHlp_IsaSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
625 PVM pVM = pDevIns->Internal.s.pVMRC;
626
627 pdmLock(pVM);
628 pdmRCIsaSetIrq(pDevIns->Internal.s.pVMRC, iIrq, iLevel, uTagSrc);
629 pdmUnlock(pVM);
630}
631
632
633/** @interface_method_impl{PDMPCIHLPRC,pfnIoApicSetIrq} */
634static DECLCALLBACK(void) pdmRCPciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
635{
636 PDMDEV_ASSERT_DEVINS(pDevIns);
637 Log4(("pdmRCPciHlp_IoApicSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
638 PVM pVM = pDevIns->Internal.s.pVMRC;
639
640 if (pVM->pdm.s.IoApic.pDevInsRC)
641 {
642 pdmLock(pVM);
643 pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel, uTagSrc);
644 pdmUnlock(pVM);
645 }
646 else if (pVM->pdm.s.IoApic.pDevInsR3)
647 {
648 /* queue for ring-3 execution. */
649 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
650 if (pTask)
651 {
652 pTask->enmOp = PDMDEVHLPTASKOP_IOAPIC_SET_IRQ;
653 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
654 pTask->u.SetIRQ.iIrq = iIrq;
655 pTask->u.SetIRQ.iLevel = iLevel;
656 pTask->u.SetIRQ.uTagSrc = uTagSrc;
657
658 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
659 }
660 else
661 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
662 }
663}
664
665
666/** @interface_method_impl{PDMPCIHLPRC,pfnIoApicSendMsi} */
667static DECLCALLBACK(void) pdmRCPciHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc)
668{
669 PDMDEV_ASSERT_DEVINS(pDevIns);
670 Log4(("pdmRCPciHlp_IoApicSendMsi: GCPhys=%p uValue=%d uTagSrc=%#x\n", GCPhys, uValue, uTagSrc));
671 PVM pVM = pDevIns->Internal.s.pVMRC;
672
673 if (pVM->pdm.s.IoApic.pDevInsRC)
674 {
675 pdmLock(pVM);
676 pVM->pdm.s.IoApic.pfnSendMsiRC(pVM->pdm.s.IoApic.pDevInsRC, GCPhys, uValue, uTagSrc);
677 pdmUnlock(pVM);
678 }
679 else
680 {
681 AssertFatalMsgFailed(("Lazy bastarts!"));
682 }
683}
684
685
686/** @interface_method_impl{PDMPCIHLPRC,pfnLock} */
687static DECLCALLBACK(int) pdmRCPciHlp_Lock(PPDMDEVINS pDevIns, int rc)
688{
689 PDMDEV_ASSERT_DEVINS(pDevIns);
690 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
691}
692
693
694/** @interface_method_impl{PDMPCIHLPRC,pfnUnlock} */
695static DECLCALLBACK(void) pdmRCPciHlp_Unlock(PPDMDEVINS pDevIns)
696{
697 PDMDEV_ASSERT_DEVINS(pDevIns);
698 pdmUnlock(pDevIns->Internal.s.pVMRC);
699}
700
701
702/**
703 * The Raw-Mode Context PCI Bus Helper Callbacks.
704 */
705extern DECLEXPORT(const PDMPCIHLPRC) g_pdmRCPciHlp =
706{
707 PDM_PCIHLPRC_VERSION,
708 pdmRCPciHlp_IsaSetIrq,
709 pdmRCPciHlp_IoApicSetIrq,
710 pdmRCPciHlp_IoApicSendMsi,
711 pdmRCPciHlp_Lock,
712 pdmRCPciHlp_Unlock,
713 PDM_PCIHLPRC_VERSION, /* the end */
714};
715
716/** @} */
717
718
719
720
721/** @name HPET RC Helpers
722 * @{
723 */
724
725
726/**
727 * The Raw-Mode Context HPET Helper Callbacks.
728 */
729extern DECLEXPORT(const PDMHPETHLPRC) g_pdmRCHpetHlp =
730{
731 PDM_HPETHLPRC_VERSION,
732 PDM_HPETHLPRC_VERSION, /* the end */
733};
734
735/** @} */
736
737
738
739
740/** @name Raw-Mode Context Driver Helpers
741 * @{
742 */
743
744/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetError} */
745static DECLCALLBACK(int) pdmRCDrvHlp_VMSetError(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
746{
747 PDMDRV_ASSERT_DRVINS(pDrvIns);
748 va_list args;
749 va_start(args, pszFormat);
750 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
751 va_end(args);
752 return rc;
753}
754
755
756/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetErrorV} */
757static DECLCALLBACK(int) pdmRCDrvHlp_VMSetErrorV(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
758{
759 PDMDRV_ASSERT_DRVINS(pDrvIns);
760 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
761 return rc;
762}
763
764
765/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetRuntimeError} */
766static DECLCALLBACK(int) pdmRCDrvHlp_VMSetRuntimeError(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
767{
768 PDMDRV_ASSERT_DRVINS(pDrvIns);
769 va_list va;
770 va_start(va, pszFormat);
771 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
772 va_end(va);
773 return rc;
774}
775
776
777/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetErrorV} */
778static DECLCALLBACK(int) pdmRCDrvHlp_VMSetRuntimeErrorV(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
779{
780 PDMDRV_ASSERT_DRVINS(pDrvIns);
781 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
782 return rc;
783}
784
785
786/** @interface_method_impl{PDMDRVHLPRC,pfnAssertEMT} */
787static DECLCALLBACK(bool) pdmRCDrvHlp_AssertEMT(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
788{
789 PDMDRV_ASSERT_DRVINS(pDrvIns);
790 if (VM_IS_EMT(pDrvIns->Internal.s.pVMRC))
791 return true;
792
793 RTAssertMsg1Weak("AssertEMT", iLine, pszFile, pszFunction);
794 RTAssertPanic();
795 return false;
796}
797
798
799/** @interface_method_impl{PDMDRVHLPRC,pfnAssertOther} */
800static DECLCALLBACK(bool) pdmRCDrvHlp_AssertOther(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
801{
802 PDMDRV_ASSERT_DRVINS(pDrvIns);
803 if (!VM_IS_EMT(pDrvIns->Internal.s.pVMRC))
804 return true;
805
806 /* Note: While we don't have any other threads but EMT(0) in RC, might
807 still have drive code compiled in which it shouldn't execute. */
808 RTAssertMsg1Weak("AssertOther", iLine, pszFile, pszFunction);
809 RTAssertPanic();
810 return false;
811}
812
813
814/** @interface_method_impl{PDMDRVHLPRC,pfnFTSetCheckpoint} */
815static DECLCALLBACK(int) pdmRCDrvHlp_FTSetCheckpoint(PPDMDRVINS pDrvIns, FTMCHECKPOINTTYPE enmType)
816{
817 PDMDRV_ASSERT_DRVINS(pDrvIns);
818 return FTMSetCheckpoint(pDrvIns->Internal.s.pVMRC, enmType);
819}
820
821
822/**
823 * The Raw-Mode Context Driver Helper Callbacks.
824 */
825extern DECLEXPORT(const PDMDRVHLPRC) g_pdmRCDrvHlp =
826{
827 PDM_DRVHLPRC_VERSION,
828 pdmRCDrvHlp_VMSetError,
829 pdmRCDrvHlp_VMSetErrorV,
830 pdmRCDrvHlp_VMSetRuntimeError,
831 pdmRCDrvHlp_VMSetRuntimeErrorV,
832 pdmRCDrvHlp_AssertEMT,
833 pdmRCDrvHlp_AssertOther,
834 pdmRCDrvHlp_FTSetCheckpoint,
835 PDM_DRVHLPRC_VERSION
836};
837
838/** @} */
839
840
841
842
843/**
844 * Sets an irq on the PIC and I/O APIC.
845 *
846 * @returns true if delivered, false if postponed.
847 * @param pVM The VM handle.
848 * @param iIrq The irq.
849 * @param iLevel The new level.
850 * @param uTagSrc The IRQ tag and source.
851 *
852 * @remarks The caller holds the PDM lock.
853 */
854static bool pdmRCIsaSetIrq(PVM pVM, int iIrq, int iLevel, uint32_t uTagSrc)
855{
856 if (RT_LIKELY( ( pVM->pdm.s.IoApic.pDevInsRC
857 || !pVM->pdm.s.IoApic.pDevInsR3)
858 && ( pVM->pdm.s.Pic.pDevInsRC
859 || !pVM->pdm.s.Pic.pDevInsR3)))
860 {
861 if (pVM->pdm.s.Pic.pDevInsRC)
862 pVM->pdm.s.Pic.pfnSetIrqRC(pVM->pdm.s.Pic.pDevInsRC, iIrq, iLevel, uTagSrc);
863 if (pVM->pdm.s.IoApic.pDevInsRC)
864 pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel, uTagSrc);
865 return true;
866 }
867
868 /* queue for ring-3 execution. */
869 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
870 AssertReturn(pTask, false);
871
872 pTask->enmOp = PDMDEVHLPTASKOP_ISA_SET_IRQ;
873 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
874 pTask->u.SetIRQ.iIrq = iIrq;
875 pTask->u.SetIRQ.iLevel = iLevel;
876 pTask->u.SetIRQ.uTagSrc = uTagSrc;
877
878 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
879 return false;
880}
881
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette