VirtualBox

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

Last change on this file since 55980 was 55899, checked in by vboxsync, 10 years ago

PGM: Added an access origin to memory read & write calls that respects handlers. This will later be passed to the access handler, so that things like the page pool (and potentially others) can query IEM about instruction details when needed.

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