VirtualBox

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

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

Cleanups related to pci bus master memory access (#1871).

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