VirtualBox

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

Last change on this file since 64378 was 64378, checked in by vboxsync, 8 years ago

PDM,Devices: Support for multiple PCI devices/function in a single PDM device.

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