VirtualBox

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

Last change on this file since 79846 was 78438, checked in by vboxsync, 6 years ago

VMM: More refactoring of GVM & VM structures for bugref:9217

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