VirtualBox

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

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

Remove the old, unused I/O APIC code and related define.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 26.4 KB
Line 
1/* $Id: PDMRCDevice.cpp 65338 2017-01-16 14:11:15Z 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#include <VBox/vmm/apic.h>
32
33#include <VBox/log.h>
34#include <VBox/err.h>
35#include <iprt/asm.h>
36#include <iprt/assert.h>
37#include <iprt/string.h>
38
39#include "dtrace/VBoxVMM.h"
40#include "PDMInline.h"
41
42
43/*********************************************************************************************************************************
44* Global Variables *
45*********************************************************************************************************************************/
46RT_C_DECLS_BEGIN
47extern DECLEXPORT(const PDMDEVHLPRC) g_pdmRCDevHlp;
48extern DECLEXPORT(const PDMPICHLPRC) g_pdmRCPicHlp;
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 /** @todo r=ramshankar: Propagating rcRZ and make all callers handle it? */
436 APICLocalInterrupt(pVCpu, 0 /* u8Pin */, 1 /* u8Level */, VINF_SUCCESS /* rcRZ */);
437}
438
439
440/** @interface_method_impl{PDMPICHLPRC,pfnClearInterruptFF} */
441static DECLCALLBACK(void) pdmRCPicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
442{
443 PDMDEV_ASSERT_DEVINS(pDevIns);
444 PVM pVM = pDevIns->Internal.s.CTX_SUFF(pVM);
445 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
446 /** @todo r=ramshankar: Propagating rcRZ and make all callers handle it? */
447 APICLocalInterrupt(pVCpu, 0 /* u8Pin */, 0 /* u8Level */, VINF_SUCCESS /* rcRZ */);
448}
449
450
451/** @interface_method_impl{PDMPICHLPRC,pfnLock} */
452static DECLCALLBACK(int) pdmRCPicHlp_Lock(PPDMDEVINS pDevIns, int rc)
453{
454 PDMDEV_ASSERT_DEVINS(pDevIns);
455 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
456}
457
458
459/** @interface_method_impl{PDMPICHLPRC,pfnUnlock} */
460static DECLCALLBACK(void) pdmRCPicHlp_Unlock(PPDMDEVINS pDevIns)
461{
462 PDMDEV_ASSERT_DEVINS(pDevIns);
463 pdmUnlock(pDevIns->Internal.s.pVMRC);
464}
465
466
467/**
468 * The Raw-Mode Context PIC Helper Callbacks.
469 */
470extern DECLEXPORT(const PDMPICHLPRC) g_pdmRCPicHlp =
471{
472 PDM_PICHLPRC_VERSION,
473 pdmRCPicHlp_SetInterruptFF,
474 pdmRCPicHlp_ClearInterruptFF,
475 pdmRCPicHlp_Lock,
476 pdmRCPicHlp_Unlock,
477 PDM_PICHLPRC_VERSION
478};
479
480/** @} */
481
482
483/** @name I/O APIC RC Helpers
484 * @{
485 */
486
487/** @interface_method_impl{PDMIOAPICHLPRC,pfnApicBusDeliver} */
488static DECLCALLBACK(int) pdmRCIoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode,
489 uint8_t u8DeliveryMode, uint8_t uVector, uint8_t u8Polarity,
490 uint8_t u8TriggerMode, uint32_t uTagSrc)
491{
492 PDMDEV_ASSERT_DEVINS(pDevIns);
493 PVM pVM = pDevIns->Internal.s.pVMRC;
494 LogFlow(("pdmRCIoApicHlp_ApicBusDeliver: caller=%p/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 uVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8 uTagSrc=%#x\n",
495 pDevIns, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, uVector, u8Polarity, u8TriggerMode, uTagSrc));
496 return APICBusDeliver(pVM, u8Dest, u8DestMode, u8DeliveryMode, uVector, u8Polarity, u8TriggerMode, uTagSrc);
497}
498
499
500/** @interface_method_impl{PDMIOAPICHLPRC,pfnLock} */
501static DECLCALLBACK(int) pdmRCIoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
502{
503 PDMDEV_ASSERT_DEVINS(pDevIns);
504 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
505}
506
507
508/** @interface_method_impl{PDMIOAPICHLPRC,pfnUnlock} */
509static DECLCALLBACK(void) pdmRCIoApicHlp_Unlock(PPDMDEVINS pDevIns)
510{
511 PDMDEV_ASSERT_DEVINS(pDevIns);
512 pdmUnlock(pDevIns->Internal.s.pVMRC);
513}
514
515
516/**
517 * The Raw-Mode Context I/O APIC Helper Callbacks.
518 */
519extern DECLEXPORT(const PDMIOAPICHLPRC) g_pdmRCIoApicHlp =
520{
521 PDM_IOAPICHLPRC_VERSION,
522 pdmRCIoApicHlp_ApicBusDeliver,
523 pdmRCIoApicHlp_Lock,
524 pdmRCIoApicHlp_Unlock,
525 PDM_IOAPICHLPRC_VERSION
526};
527
528/** @} */
529
530
531
532
533/** @name PCI Bus RC Helpers
534 * @{
535 */
536
537/** @interface_method_impl{PDMPCIHLPRC,pfnIsaSetIrq} */
538static DECLCALLBACK(void) pdmRCPciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
539{
540 PDMDEV_ASSERT_DEVINS(pDevIns);
541 Log4(("pdmRCPciHlp_IsaSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
542 PVM pVM = pDevIns->Internal.s.pVMRC;
543
544 pdmLock(pVM);
545 pdmRCIsaSetIrq(pDevIns->Internal.s.pVMRC, iIrq, iLevel, uTagSrc);
546 pdmUnlock(pVM);
547}
548
549
550/** @interface_method_impl{PDMPCIHLPRC,pfnIoApicSetIrq} */
551static DECLCALLBACK(void) pdmRCPciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
552{
553 PDMDEV_ASSERT_DEVINS(pDevIns);
554 Log4(("pdmRCPciHlp_IoApicSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
555 PVM pVM = pDevIns->Internal.s.pVMRC;
556
557 if (pVM->pdm.s.IoApic.pDevInsRC)
558 pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel, uTagSrc);
559 else if (pVM->pdm.s.IoApic.pDevInsR3)
560 {
561 /* queue for ring-3 execution. */
562 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
563 if (pTask)
564 {
565 pTask->enmOp = PDMDEVHLPTASKOP_IOAPIC_SET_IRQ;
566 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
567 pTask->u.IoApicSetIRQ.iIrq = iIrq;
568 pTask->u.IoApicSetIRQ.iLevel = iLevel;
569 pTask->u.IoApicSetIRQ.uTagSrc = uTagSrc;
570
571 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
572 }
573 else
574 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
575 }
576}
577
578
579/** @interface_method_impl{PDMPCIHLPRC,pfnIoApicSendMsi} */
580static DECLCALLBACK(void) pdmRCPciHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc)
581{
582 PDMDEV_ASSERT_DEVINS(pDevIns);
583 Log4(("pdmRCPciHlp_IoApicSendMsi: GCPhys=%p uValue=%d uTagSrc=%#x\n", GCPhys, uValue, uTagSrc));
584 PVM pVM = pDevIns->Internal.s.pVMRC;
585
586 if (pVM->pdm.s.IoApic.pDevInsRC)
587 pVM->pdm.s.IoApic.pfnSendMsiRC(pVM->pdm.s.IoApic.pDevInsRC, GCPhys, uValue, uTagSrc);
588 else
589 AssertFatalMsgFailed(("Lazy bastarts!"));
590}
591
592
593/** @interface_method_impl{PDMPCIHLPRC,pfnLock} */
594static DECLCALLBACK(int) pdmRCPciHlp_Lock(PPDMDEVINS pDevIns, int rc)
595{
596 PDMDEV_ASSERT_DEVINS(pDevIns);
597 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
598}
599
600
601/** @interface_method_impl{PDMPCIHLPRC,pfnUnlock} */
602static DECLCALLBACK(void) pdmRCPciHlp_Unlock(PPDMDEVINS pDevIns)
603{
604 PDMDEV_ASSERT_DEVINS(pDevIns);
605 pdmUnlock(pDevIns->Internal.s.pVMRC);
606}
607
608
609/**
610 * The Raw-Mode Context PCI Bus Helper Callbacks.
611 */
612extern DECLEXPORT(const PDMPCIHLPRC) g_pdmRCPciHlp =
613{
614 PDM_PCIHLPRC_VERSION,
615 pdmRCPciHlp_IsaSetIrq,
616 pdmRCPciHlp_IoApicSetIrq,
617 pdmRCPciHlp_IoApicSendMsi,
618 pdmRCPciHlp_Lock,
619 pdmRCPciHlp_Unlock,
620 PDM_PCIHLPRC_VERSION, /* the end */
621};
622
623/** @} */
624
625
626
627
628/** @name HPET RC Helpers
629 * @{
630 */
631
632
633/**
634 * The Raw-Mode Context HPET Helper Callbacks.
635 */
636extern DECLEXPORT(const PDMHPETHLPRC) g_pdmRCHpetHlp =
637{
638 PDM_HPETHLPRC_VERSION,
639 PDM_HPETHLPRC_VERSION, /* the end */
640};
641
642/** @} */
643
644
645
646
647/** @name Raw-Mode Context Driver Helpers
648 * @{
649 */
650
651/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetError} */
652static DECLCALLBACK(int) pdmRCDrvHlp_VMSetError(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
653{
654 PDMDRV_ASSERT_DRVINS(pDrvIns);
655 va_list args;
656 va_start(args, pszFormat);
657 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
658 va_end(args);
659 return rc;
660}
661
662
663/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetErrorV} */
664static DECLCALLBACK(int) pdmRCDrvHlp_VMSetErrorV(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
665{
666 PDMDRV_ASSERT_DRVINS(pDrvIns);
667 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
668 return rc;
669}
670
671
672/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetRuntimeError} */
673static DECLCALLBACK(int) pdmRCDrvHlp_VMSetRuntimeError(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
674{
675 PDMDRV_ASSERT_DRVINS(pDrvIns);
676 va_list va;
677 va_start(va, pszFormat);
678 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
679 va_end(va);
680 return rc;
681}
682
683
684/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetRuntimeErrorV} */
685static DECLCALLBACK(int) pdmRCDrvHlp_VMSetRuntimeErrorV(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
686{
687 PDMDRV_ASSERT_DRVINS(pDrvIns);
688 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
689 return rc;
690}
691
692
693/** @interface_method_impl{PDMDRVHLPRC,pfnAssertEMT} */
694static DECLCALLBACK(bool) pdmRCDrvHlp_AssertEMT(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
695{
696 PDMDRV_ASSERT_DRVINS(pDrvIns); RT_NOREF_PV(pDrvIns);
697 if (VM_IS_EMT(pDrvIns->Internal.s.pVMRC))
698 return true;
699
700 RTAssertMsg1Weak("AssertEMT", iLine, pszFile, pszFunction);
701 RTAssertPanic();
702 return false;
703}
704
705
706/** @interface_method_impl{PDMDRVHLPRC,pfnAssertOther} */
707static DECLCALLBACK(bool) pdmRCDrvHlp_AssertOther(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
708{
709 PDMDRV_ASSERT_DRVINS(pDrvIns); RT_NOREF_PV(pDrvIns);
710 if (!VM_IS_EMT(pDrvIns->Internal.s.pVMRC))
711 return true;
712
713 /* Note: While we don't have any other threads but EMT(0) in RC, might
714 still have drive code compiled in which it shouldn't execute. */
715 RTAssertMsg1Weak("AssertOther", iLine, pszFile, pszFunction);
716 RTAssertPanic();
717 RT_NOREF_PV(pszFile); RT_NOREF_PV(iLine); RT_NOREF_PV(pszFunction);
718 return false;
719}
720
721
722/** @interface_method_impl{PDMDRVHLPRC,pfnFTSetCheckpoint} */
723static DECLCALLBACK(int) pdmRCDrvHlp_FTSetCheckpoint(PPDMDRVINS pDrvIns, FTMCHECKPOINTTYPE enmType)
724{
725 PDMDRV_ASSERT_DRVINS(pDrvIns);
726 return FTMSetCheckpoint(pDrvIns->Internal.s.pVMRC, enmType);
727}
728
729
730/**
731 * The Raw-Mode Context Driver Helper Callbacks.
732 */
733extern DECLEXPORT(const PDMDRVHLPRC) g_pdmRCDrvHlp =
734{
735 PDM_DRVHLPRC_VERSION,
736 pdmRCDrvHlp_VMSetError,
737 pdmRCDrvHlp_VMSetErrorV,
738 pdmRCDrvHlp_VMSetRuntimeError,
739 pdmRCDrvHlp_VMSetRuntimeErrorV,
740 pdmRCDrvHlp_AssertEMT,
741 pdmRCDrvHlp_AssertOther,
742 pdmRCDrvHlp_FTSetCheckpoint,
743 PDM_DRVHLPRC_VERSION
744};
745
746/** @} */
747
748
749
750
751/**
752 * Sets an irq on the PIC and I/O APIC.
753 *
754 * @returns true if delivered, false if postponed.
755 * @param pVM The cross context VM structure.
756 * @param iIrq The irq.
757 * @param iLevel The new level.
758 * @param uTagSrc The IRQ tag and source.
759 *
760 * @remarks The caller holds the PDM lock.
761 */
762static bool pdmRCIsaSetIrq(PVM pVM, int iIrq, int iLevel, uint32_t uTagSrc)
763{
764 if (RT_LIKELY( ( pVM->pdm.s.IoApic.pDevInsRC
765 || !pVM->pdm.s.IoApic.pDevInsR3)
766 && ( pVM->pdm.s.Pic.pDevInsRC
767 || !pVM->pdm.s.Pic.pDevInsR3)))
768 {
769 if (pVM->pdm.s.Pic.pDevInsRC)
770 pVM->pdm.s.Pic.pfnSetIrqRC(pVM->pdm.s.Pic.pDevInsRC, iIrq, iLevel, uTagSrc);
771 if (pVM->pdm.s.IoApic.pDevInsRC)
772 pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel, uTagSrc);
773 return true;
774 }
775
776 /* queue for ring-3 execution. */
777 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
778 AssertReturn(pTask, false);
779
780 pTask->enmOp = PDMDEVHLPTASKOP_ISA_SET_IRQ;
781 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
782 pTask->u.IsaSetIRQ.iIrq = iIrq;
783 pTask->u.IsaSetIRQ.iLevel = iLevel;
784 pTask->u.IsaSetIRQ.uTagSrc = uTagSrc;
785
786 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
787 return false;
788}
789
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