VirtualBox

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

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

PDM: Address the todos for cleaning up the PDMDEVHLP structure, bring the reserved slots back to the nominal numver and bump the major version (20 ended up being used by 5.1). Eliminate redundant PDMDEVHLP version dependent conditional compilation

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 27.3 KB
Line 
1/* $Id: PDMRCDevice.cpp 68594 2017-08-31 14:24:09Z 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,pfnIoApicSendMsi} */
210static DECLCALLBACK(void) pdmRCDevHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue)
211{
212 PDMDEV_ASSERT_DEVINS(pDevIns);
213 LogFlow(("pdmRCDevHlp_IoApicSendMsi: caller=%p/%d: GCPhys=%RGp uValue=%#x\n", pDevIns, pDevIns->iInstance, GCPhys, uValue));
214 PVM pVM = pDevIns->Internal.s.pVMRC;
215
216 uint32_t uTagSrc;
217 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
218 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
219
220 if (pVM->pdm.s.IoApic.pDevInsRC)
221 pVM->pdm.s.IoApic.pfnSendMsiRC(pVM->pdm.s.IoApic.pDevInsRC, GCPhys, uValue, uTagSrc);
222 else
223 AssertFatalMsgFailed(("Lazy bastards!"));
224
225 LogFlow(("pdmRCDevHlp_IoApicSendMsi: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, uTagSrc));
226}
227
228
229/** @interface_method_impl{PDMDEVHLPRC,pfnPhysRead} */
230static DECLCALLBACK(int) pdmRCDevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
231{
232 PDMDEV_ASSERT_DEVINS(pDevIns);
233 LogFlow(("pdmRCDevHlp_PhysRead: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
234 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
235
236 VBOXSTRICTRC rcStrict = PGMPhysRead(pDevIns->Internal.s.pVMRC, GCPhys, pvBuf, cbRead, PGMACCESSORIGIN_DEVICE);
237 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
238
239 Log(("pdmRCDevHlp_PhysRead: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
240 return VBOXSTRICTRC_VAL(rcStrict);
241}
242
243
244/** @interface_method_impl{PDMDEVHLPRC,pfnPhysWrite} */
245static DECLCALLBACK(int) pdmRCDevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
246{
247 PDMDEV_ASSERT_DEVINS(pDevIns);
248 LogFlow(("pdmRCDevHlp_PhysWrite: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
249 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
250
251 VBOXSTRICTRC rcStrict = PGMPhysWrite(pDevIns->Internal.s.pVMRC, GCPhys, pvBuf, cbWrite, PGMACCESSORIGIN_DEVICE);
252 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
253
254 Log(("pdmRCDevHlp_PhysWrite: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
255 return VBOXSTRICTRC_VAL(rcStrict);
256}
257
258
259/** @interface_method_impl{PDMDEVHLPRC,pfnA20IsEnabled} */
260static DECLCALLBACK(bool) pdmRCDevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
261{
262 PDMDEV_ASSERT_DEVINS(pDevIns);
263 LogFlow(("pdmRCDevHlp_A20IsEnabled: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
264
265 bool fEnabled = PGMPhysIsA20Enabled(VMMGetCpu0(pDevIns->Internal.s.pVMRC));
266
267 Log(("pdmRCDevHlp_A20IsEnabled: caller=%p/%d: returns %RTbool\n", pDevIns, pDevIns->iInstance, fEnabled));
268 return fEnabled;
269}
270
271
272/** @interface_method_impl{PDMDEVHLPRC,pfnVMState} */
273static DECLCALLBACK(VMSTATE) pdmRCDevHlp_VMState(PPDMDEVINS pDevIns)
274{
275 PDMDEV_ASSERT_DEVINS(pDevIns);
276
277 VMSTATE enmVMState = pDevIns->Internal.s.pVMRC->enmVMState;
278
279 LogFlow(("pdmRCDevHlp_VMState: caller=%p/%d: returns %d\n", pDevIns, pDevIns->iInstance, enmVMState));
280 return enmVMState;
281}
282
283
284/** @interface_method_impl{PDMDEVHLPRC,pfnVMSetError} */
285static DECLCALLBACK(int) pdmRCDevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
286{
287 PDMDEV_ASSERT_DEVINS(pDevIns);
288 va_list args;
289 va_start(args, pszFormat);
290 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
291 va_end(args);
292 return rc;
293}
294
295
296/** @interface_method_impl{PDMDEVHLPRC,pfnVMSetErrorV} */
297static DECLCALLBACK(int) pdmRCDevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
298{
299 PDMDEV_ASSERT_DEVINS(pDevIns);
300 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
301 return rc;
302}
303
304
305/** @interface_method_impl{PDMDEVHLPRC,pfnVMSetRuntimeError} */
306static DECLCALLBACK(int) pdmRCDevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
307{
308 PDMDEV_ASSERT_DEVINS(pDevIns);
309 va_list va;
310 va_start(va, pszFormat);
311 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
312 va_end(va);
313 return rc;
314}
315
316
317/** @interface_method_impl{PDMDEVHLPRC,pfnVMSetRuntimeErrorV} */
318static DECLCALLBACK(int) pdmRCDevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
319{
320 PDMDEV_ASSERT_DEVINS(pDevIns);
321 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
322 return rc;
323}
324
325
326/** @interface_method_impl{PDMDEVHLPRC,pfnPATMSetMMIOPatchInfo} */
327static DECLCALLBACK(int) pdmRCDevHlp_PATMSetMMIOPatchInfo(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPTR pCachedData)
328{
329 PDMDEV_ASSERT_DEVINS(pDevIns);
330 LogFlow(("pdmRCDevHlp_PATMSetMMIOPatchInfo: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
331
332 return PATMSetMMIOPatchInfo(pDevIns->Internal.s.pVMRC, GCPhys, (RTRCPTR)(uintptr_t)pCachedData);
333}
334
335
336/** @interface_method_impl{PDMDEVHLPRC,pfnGetVM} */
337static DECLCALLBACK(PVM) pdmRCDevHlp_GetVM(PPDMDEVINS pDevIns)
338{
339 PDMDEV_ASSERT_DEVINS(pDevIns);
340 LogFlow(("pdmRCDevHlp_GetVM: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
341 return pDevIns->Internal.s.pVMRC;
342}
343
344
345/** @interface_method_impl{PDMDEVHLPRC,pfnGetVMCPU} */
346static DECLCALLBACK(PVMCPU) pdmRCDevHlp_GetVMCPU(PPDMDEVINS pDevIns)
347{
348 PDMDEV_ASSERT_DEVINS(pDevIns);
349 LogFlow(("pdmRCDevHlp_GetVMCPU: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
350 return VMMGetCpu(pDevIns->Internal.s.pVMRC);
351}
352
353
354/** @interface_method_impl{PDMDEVHLPRC,pfnGetCurrentCpuId} */
355static DECLCALLBACK(VMCPUID) pdmRCDevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
356{
357 PDMDEV_ASSERT_DEVINS(pDevIns);
358 VMCPUID idCpu = VMMGetCpuId(pDevIns->Internal.s.pVMRC);
359 LogFlow(("pdmRCDevHlp_GetCurrentCpuId: caller='%p'/%d for CPU %u\n", pDevIns, pDevIns->iInstance, idCpu));
360 return idCpu;
361}
362
363
364/** @interface_method_impl{PDMDEVHLPRC,pfnTMTimeVirtGet} */
365static DECLCALLBACK(uint64_t) pdmRCDevHlp_TMTimeVirtGet(PPDMDEVINS pDevIns)
366{
367 PDMDEV_ASSERT_DEVINS(pDevIns);
368 LogFlow(("pdmRCDevHlp_TMTimeVirtGet: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
369 return TMVirtualGet(pDevIns->Internal.s.pVMRC);
370}
371
372
373/** @interface_method_impl{PDMDEVHLPRC,pfnTMTimeVirtGetFreq} */
374static DECLCALLBACK(uint64_t) pdmRCDevHlp_TMTimeVirtGetFreq(PPDMDEVINS pDevIns)
375{
376 PDMDEV_ASSERT_DEVINS(pDevIns);
377 LogFlow(("pdmRCDevHlp_TMTimeVirtGetFreq: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
378 return TMVirtualGetFreq(pDevIns->Internal.s.pVMRC);
379}
380
381
382/** @interface_method_impl{PDMDEVHLPRC,pfnTMTimeVirtGetNano} */
383static DECLCALLBACK(uint64_t) pdmRCDevHlp_TMTimeVirtGetNano(PPDMDEVINS pDevIns)
384{
385 PDMDEV_ASSERT_DEVINS(pDevIns);
386 LogFlow(("pdmRCDevHlp_TMTimeVirtGetNano: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
387 return TMVirtualToNano(pDevIns->Internal.s.pVMRC, TMVirtualGet(pDevIns->Internal.s.pVMRC));
388}
389
390
391/** @interface_method_impl{PDMDEVHLPRC,pfnDBGFTraceBuf} */
392static DECLCALLBACK(RTTRACEBUF) pdmRCDevHlp_DBGFTraceBuf(PPDMDEVINS pDevIns)
393{
394 PDMDEV_ASSERT_DEVINS(pDevIns);
395 RTTRACEBUF hTraceBuf = pDevIns->Internal.s.pVMRC->hTraceBufRC;
396 LogFlow(("pdmRCDevHlp_DBGFTraceBuf: caller='%p'/%d: returns %p\n", pDevIns, pDevIns->iInstance, hTraceBuf));
397 return hTraceBuf;
398}
399
400
401/**
402 * The Raw-Mode Context Device Helper Callbacks.
403 */
404extern DECLEXPORT(const PDMDEVHLPRC) g_pdmRCDevHlp =
405{
406 PDM_DEVHLPRC_VERSION,
407 pdmRCDevHlp_PCIPhysRead,
408 pdmRCDevHlp_PCIPhysWrite,
409 pdmRCDevHlp_PCISetIrq,
410 pdmRCDevHlp_ISASetIrq,
411 pdmRCDevHlp_IoApicSendMsi,
412 pdmRCDevHlp_PhysRead,
413 pdmRCDevHlp_PhysWrite,
414 pdmRCDevHlp_A20IsEnabled,
415 pdmRCDevHlp_VMState,
416 pdmRCDevHlp_VMSetError,
417 pdmRCDevHlp_VMSetErrorV,
418 pdmRCDevHlp_VMSetRuntimeError,
419 pdmRCDevHlp_VMSetRuntimeErrorV,
420 pdmRCDevHlp_PATMSetMMIOPatchInfo,
421 pdmRCDevHlp_GetVM,
422 pdmRCDevHlp_GetVMCPU,
423 pdmRCDevHlp_GetCurrentCpuId,
424 pdmRCDevHlp_TMTimeVirtGet,
425 pdmRCDevHlp_TMTimeVirtGetFreq,
426 pdmRCDevHlp_TMTimeVirtGetNano,
427 pdmRCDevHlp_DBGFTraceBuf,
428 NULL,
429 NULL,
430 NULL,
431 NULL,
432 NULL,
433 NULL,
434 NULL,
435 NULL,
436 NULL,
437 NULL,
438 PDM_DEVHLPRC_VERSION
439};
440
441/** @} */
442
443
444
445
446/** @name PIC RC Helpers
447 * @{
448 */
449
450/** @interface_method_impl{PDMPICHLPRC,pfnSetInterruptFF} */
451static DECLCALLBACK(void) pdmRCPicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
452{
453 PDMDEV_ASSERT_DEVINS(pDevIns);
454 PVM pVM = pDevIns->Internal.s.pVMRC;
455 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
456 /** @todo r=ramshankar: Propagating rcRZ and make all callers handle it? */
457 APICLocalInterrupt(pVCpu, 0 /* u8Pin */, 1 /* u8Level */, VINF_SUCCESS /* rcRZ */);
458}
459
460
461/** @interface_method_impl{PDMPICHLPRC,pfnClearInterruptFF} */
462static DECLCALLBACK(void) pdmRCPicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
463{
464 PDMDEV_ASSERT_DEVINS(pDevIns);
465 PVM pVM = pDevIns->Internal.s.CTX_SUFF(pVM);
466 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
467 /** @todo r=ramshankar: Propagating rcRZ and make all callers handle it? */
468 APICLocalInterrupt(pVCpu, 0 /* u8Pin */, 0 /* u8Level */, VINF_SUCCESS /* rcRZ */);
469}
470
471
472/** @interface_method_impl{PDMPICHLPRC,pfnLock} */
473static DECLCALLBACK(int) pdmRCPicHlp_Lock(PPDMDEVINS pDevIns, int rc)
474{
475 PDMDEV_ASSERT_DEVINS(pDevIns);
476 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
477}
478
479
480/** @interface_method_impl{PDMPICHLPRC,pfnUnlock} */
481static DECLCALLBACK(void) pdmRCPicHlp_Unlock(PPDMDEVINS pDevIns)
482{
483 PDMDEV_ASSERT_DEVINS(pDevIns);
484 pdmUnlock(pDevIns->Internal.s.pVMRC);
485}
486
487
488/**
489 * The Raw-Mode Context PIC Helper Callbacks.
490 */
491extern DECLEXPORT(const PDMPICHLPRC) g_pdmRCPicHlp =
492{
493 PDM_PICHLPRC_VERSION,
494 pdmRCPicHlp_SetInterruptFF,
495 pdmRCPicHlp_ClearInterruptFF,
496 pdmRCPicHlp_Lock,
497 pdmRCPicHlp_Unlock,
498 PDM_PICHLPRC_VERSION
499};
500
501/** @} */
502
503
504/** @name I/O APIC RC Helpers
505 * @{
506 */
507
508/** @interface_method_impl{PDMIOAPICHLPRC,pfnApicBusDeliver} */
509static DECLCALLBACK(int) pdmRCIoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode,
510 uint8_t u8DeliveryMode, uint8_t uVector, uint8_t u8Polarity,
511 uint8_t u8TriggerMode, uint32_t uTagSrc)
512{
513 PDMDEV_ASSERT_DEVINS(pDevIns);
514 PVM pVM = pDevIns->Internal.s.pVMRC;
515 LogFlow(("pdmRCIoApicHlp_ApicBusDeliver: caller=%p/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 uVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8 uTagSrc=%#x\n",
516 pDevIns, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, uVector, u8Polarity, u8TriggerMode, uTagSrc));
517 return APICBusDeliver(pVM, u8Dest, u8DestMode, u8DeliveryMode, uVector, u8Polarity, u8TriggerMode, uTagSrc);
518}
519
520
521/** @interface_method_impl{PDMIOAPICHLPRC,pfnLock} */
522static DECLCALLBACK(int) pdmRCIoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
523{
524 PDMDEV_ASSERT_DEVINS(pDevIns);
525 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
526}
527
528
529/** @interface_method_impl{PDMIOAPICHLPRC,pfnUnlock} */
530static DECLCALLBACK(void) pdmRCIoApicHlp_Unlock(PPDMDEVINS pDevIns)
531{
532 PDMDEV_ASSERT_DEVINS(pDevIns);
533 pdmUnlock(pDevIns->Internal.s.pVMRC);
534}
535
536
537/**
538 * The Raw-Mode Context I/O APIC Helper Callbacks.
539 */
540extern DECLEXPORT(const PDMIOAPICHLPRC) g_pdmRCIoApicHlp =
541{
542 PDM_IOAPICHLPRC_VERSION,
543 pdmRCIoApicHlp_ApicBusDeliver,
544 pdmRCIoApicHlp_Lock,
545 pdmRCIoApicHlp_Unlock,
546 PDM_IOAPICHLPRC_VERSION
547};
548
549/** @} */
550
551
552
553
554/** @name PCI Bus RC Helpers
555 * @{
556 */
557
558/** @interface_method_impl{PDMPCIHLPRC,pfnIsaSetIrq} */
559static DECLCALLBACK(void) pdmRCPciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
560{
561 PDMDEV_ASSERT_DEVINS(pDevIns);
562 Log4(("pdmRCPciHlp_IsaSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
563 PVM pVM = pDevIns->Internal.s.pVMRC;
564
565 pdmLock(pVM);
566 pdmRCIsaSetIrq(pDevIns->Internal.s.pVMRC, iIrq, iLevel, uTagSrc);
567 pdmUnlock(pVM);
568}
569
570
571/** @interface_method_impl{PDMPCIHLPRC,pfnIoApicSetIrq} */
572static DECLCALLBACK(void) pdmRCPciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
573{
574 PDMDEV_ASSERT_DEVINS(pDevIns);
575 Log4(("pdmRCPciHlp_IoApicSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
576 PVM pVM = pDevIns->Internal.s.pVMRC;
577
578 if (pVM->pdm.s.IoApic.pDevInsRC)
579 pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel, uTagSrc);
580 else if (pVM->pdm.s.IoApic.pDevInsR3)
581 {
582 /* queue for ring-3 execution. */
583 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
584 if (pTask)
585 {
586 pTask->enmOp = PDMDEVHLPTASKOP_IOAPIC_SET_IRQ;
587 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
588 pTask->u.IoApicSetIRQ.iIrq = iIrq;
589 pTask->u.IoApicSetIRQ.iLevel = iLevel;
590 pTask->u.IoApicSetIRQ.uTagSrc = uTagSrc;
591
592 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
593 }
594 else
595 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
596 }
597}
598
599
600/** @interface_method_impl{PDMPCIHLPRC,pfnIoApicSendMsi} */
601static DECLCALLBACK(void) pdmRCPciHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc)
602{
603 PDMDEV_ASSERT_DEVINS(pDevIns);
604 Log4(("pdmRCPciHlp_IoApicSendMsi: GCPhys=%p uValue=%d uTagSrc=%#x\n", GCPhys, uValue, uTagSrc));
605 PVM pVM = pDevIns->Internal.s.pVMRC;
606
607 if (pVM->pdm.s.IoApic.pDevInsRC)
608 pVM->pdm.s.IoApic.pfnSendMsiRC(pVM->pdm.s.IoApic.pDevInsRC, GCPhys, uValue, uTagSrc);
609 else
610 AssertFatalMsgFailed(("Lazy bastards!"));
611}
612
613
614/** @interface_method_impl{PDMPCIHLPRC,pfnLock} */
615static DECLCALLBACK(int) pdmRCPciHlp_Lock(PPDMDEVINS pDevIns, int rc)
616{
617 PDMDEV_ASSERT_DEVINS(pDevIns);
618 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
619}
620
621
622/** @interface_method_impl{PDMPCIHLPRC,pfnUnlock} */
623static DECLCALLBACK(void) pdmRCPciHlp_Unlock(PPDMDEVINS pDevIns)
624{
625 PDMDEV_ASSERT_DEVINS(pDevIns);
626 pdmUnlock(pDevIns->Internal.s.pVMRC);
627}
628
629
630/**
631 * The Raw-Mode Context PCI Bus Helper Callbacks.
632 */
633extern DECLEXPORT(const PDMPCIHLPRC) g_pdmRCPciHlp =
634{
635 PDM_PCIHLPRC_VERSION,
636 pdmRCPciHlp_IsaSetIrq,
637 pdmRCPciHlp_IoApicSetIrq,
638 pdmRCPciHlp_IoApicSendMsi,
639 pdmRCPciHlp_Lock,
640 pdmRCPciHlp_Unlock,
641 PDM_PCIHLPRC_VERSION, /* the end */
642};
643
644/** @} */
645
646
647
648
649/** @name HPET RC Helpers
650 * @{
651 */
652
653
654/**
655 * The Raw-Mode Context HPET Helper Callbacks.
656 */
657extern DECLEXPORT(const PDMHPETHLPRC) g_pdmRCHpetHlp =
658{
659 PDM_HPETHLPRC_VERSION,
660 PDM_HPETHLPRC_VERSION, /* the end */
661};
662
663/** @} */
664
665
666
667
668/** @name Raw-Mode Context Driver Helpers
669 * @{
670 */
671
672/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetError} */
673static DECLCALLBACK(int) pdmRCDrvHlp_VMSetError(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
674{
675 PDMDRV_ASSERT_DRVINS(pDrvIns);
676 va_list args;
677 va_start(args, pszFormat);
678 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
679 va_end(args);
680 return rc;
681}
682
683
684/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetErrorV} */
685static DECLCALLBACK(int) pdmRCDrvHlp_VMSetErrorV(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
686{
687 PDMDRV_ASSERT_DRVINS(pDrvIns);
688 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
689 return rc;
690}
691
692
693/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetRuntimeError} */
694static DECLCALLBACK(int) pdmRCDrvHlp_VMSetRuntimeError(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
695{
696 PDMDRV_ASSERT_DRVINS(pDrvIns);
697 va_list va;
698 va_start(va, pszFormat);
699 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
700 va_end(va);
701 return rc;
702}
703
704
705/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetRuntimeErrorV} */
706static DECLCALLBACK(int) pdmRCDrvHlp_VMSetRuntimeErrorV(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
707{
708 PDMDRV_ASSERT_DRVINS(pDrvIns);
709 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
710 return rc;
711}
712
713
714/** @interface_method_impl{PDMDRVHLPRC,pfnAssertEMT} */
715static DECLCALLBACK(bool) pdmRCDrvHlp_AssertEMT(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
716{
717 PDMDRV_ASSERT_DRVINS(pDrvIns); RT_NOREF_PV(pDrvIns);
718 if (VM_IS_EMT(pDrvIns->Internal.s.pVMRC))
719 return true;
720
721 RTAssertMsg1Weak("AssertEMT", iLine, pszFile, pszFunction);
722 RTAssertPanic();
723 return false;
724}
725
726
727/** @interface_method_impl{PDMDRVHLPRC,pfnAssertOther} */
728static DECLCALLBACK(bool) pdmRCDrvHlp_AssertOther(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
729{
730 PDMDRV_ASSERT_DRVINS(pDrvIns); RT_NOREF_PV(pDrvIns);
731 if (!VM_IS_EMT(pDrvIns->Internal.s.pVMRC))
732 return true;
733
734 /* Note: While we don't have any other threads but EMT(0) in RC, might
735 still have drive code compiled in which it shouldn't execute. */
736 RTAssertMsg1Weak("AssertOther", iLine, pszFile, pszFunction);
737 RTAssertPanic();
738 RT_NOREF_PV(pszFile); RT_NOREF_PV(iLine); RT_NOREF_PV(pszFunction);
739 return false;
740}
741
742
743/** @interface_method_impl{PDMDRVHLPRC,pfnFTSetCheckpoint} */
744static DECLCALLBACK(int) pdmRCDrvHlp_FTSetCheckpoint(PPDMDRVINS pDrvIns, FTMCHECKPOINTTYPE enmType)
745{
746 PDMDRV_ASSERT_DRVINS(pDrvIns);
747 return FTMSetCheckpoint(pDrvIns->Internal.s.pVMRC, enmType);
748}
749
750
751/**
752 * The Raw-Mode Context Driver Helper Callbacks.
753 */
754extern DECLEXPORT(const PDMDRVHLPRC) g_pdmRCDrvHlp =
755{
756 PDM_DRVHLPRC_VERSION,
757 pdmRCDrvHlp_VMSetError,
758 pdmRCDrvHlp_VMSetErrorV,
759 pdmRCDrvHlp_VMSetRuntimeError,
760 pdmRCDrvHlp_VMSetRuntimeErrorV,
761 pdmRCDrvHlp_AssertEMT,
762 pdmRCDrvHlp_AssertOther,
763 pdmRCDrvHlp_FTSetCheckpoint,
764 PDM_DRVHLPRC_VERSION
765};
766
767/** @} */
768
769
770
771
772/**
773 * Sets an irq on the PIC and I/O APIC.
774 *
775 * @returns true if delivered, false if postponed.
776 * @param pVM The cross context VM structure.
777 * @param iIrq The irq.
778 * @param iLevel The new level.
779 * @param uTagSrc The IRQ tag and source.
780 *
781 * @remarks The caller holds the PDM lock.
782 */
783static bool pdmRCIsaSetIrq(PVM pVM, int iIrq, int iLevel, uint32_t uTagSrc)
784{
785 if (RT_LIKELY( ( pVM->pdm.s.IoApic.pDevInsRC
786 || !pVM->pdm.s.IoApic.pDevInsR3)
787 && ( pVM->pdm.s.Pic.pDevInsRC
788 || !pVM->pdm.s.Pic.pDevInsR3)))
789 {
790 if (pVM->pdm.s.Pic.pDevInsRC)
791 pVM->pdm.s.Pic.pfnSetIrqRC(pVM->pdm.s.Pic.pDevInsRC, iIrq, iLevel, uTagSrc);
792 if (pVM->pdm.s.IoApic.pDevInsRC)
793 pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel, uTagSrc);
794 return true;
795 }
796
797 /* queue for ring-3 execution. */
798 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
799 AssertReturn(pTask, false);
800
801 pTask->enmOp = PDMDEVHLPTASKOP_ISA_SET_IRQ;
802 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
803 pTask->u.IsaSetIRQ.iIrq = iIrq;
804 pTask->u.IsaSetIRQ.iLevel = iLevel;
805 pTask->u.IsaSetIRQ.uTagSrc = uTagSrc;
806
807 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
808 return false;
809}
810
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