VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMGC/PDMGCDevice.cpp@ 32963

Last change on this file since 32963 was 32935, checked in by vboxsync, 14 years ago

PDM, VMM, PCI: reworked MSI API: now MSIs delivered via IOAPIC API, not with MMIO access, LSI logic now can work in MSI mode

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 25.1 KB
Line 
1/* $Id: PDMGCDevice.cpp 32935 2010-10-06 09:28:42Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, RC Device parts.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_PDM_DEVICE
23#include "PDMInternal.h"
24#include <VBox/pdm.h>
25#include <VBox/pgm.h>
26#include <VBox/mm.h>
27#include <VBox/vm.h>
28#include <VBox/vmm.h>
29#include <VBox/patm.h>
30
31#include <VBox/log.h>
32#include <VBox/err.h>
33#include <iprt/asm.h>
34#include <iprt/assert.h>
35#include <iprt/string.h>
36
37
38/*******************************************************************************
39* Global Variables *
40*******************************************************************************/
41RT_C_DECLS_BEGIN
42extern DECLEXPORT(const PDMDEVHLPRC) g_pdmRCDevHlp;
43extern DECLEXPORT(const PDMPICHLPRC) g_pdmRCPicHlp;
44extern DECLEXPORT(const PDMAPICHLPRC) g_pdmRCApicHlp;
45extern DECLEXPORT(const PDMIOAPICHLPRC) g_pdmRCIoApicHlp;
46extern DECLEXPORT(const PDMPCIHLPRC) g_pdmRCPciHlp;
47extern DECLEXPORT(const PDMHPETHLPRC) g_pdmRCHpetHlp;
48extern DECLEXPORT(const PDMDRVHLPRC) g_pdmRCDrvHlp;
49RT_C_DECLS_END
50
51
52/*******************************************************************************
53* Internal Functions *
54*******************************************************************************/
55static void pdmRCIsaSetIrq(PVM pVM, int iIrq, int iLevel);
56static void pdmRCIoApicSetIrq(PVM pVM, int iIrq, int iLevel);
57static void pdmRCIoApicSendMsi(PVM pVM, RTGCPHYS GCAddr, uint32_t uValue);
58
59/** @name Raw-Mode Context Device Helpers
60 * @{
61 */
62
63/** @interface_method_impl{PDMDEVHLPRC,pfnPCISetIrq} */
64static DECLCALLBACK(void) pdmRCDevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
65{
66 PDMDEV_ASSERT_DEVINS(pDevIns);
67 LogFlow(("pdmRCDevHlp_PCISetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
68
69 PVM pVM = pDevIns->Internal.s.pVMRC;
70 PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceRC;
71 PPDMPCIBUS pPciBus = pDevIns->Internal.s.pPciBusRC;
72 if ( pPciDev
73 && pPciBus
74 && pPciBus->pDevInsRC)
75 {
76 pdmLock(pVM);
77 pPciBus->pfnSetIrqRC(pPciBus->pDevInsRC, pPciDev, iIrq, iLevel);
78 pdmUnlock(pVM);
79 }
80 else
81 {
82 /* queue for ring-3 execution. */
83 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
84 if (pTask)
85 {
86 pTask->enmOp = PDMDEVHLPTASKOP_PCI_SET_IRQ;
87 pTask->pDevInsR3 = PDMDEVINS_2_R3PTR(pDevIns);
88 pTask->u.SetIRQ.iIrq = iIrq;
89 pTask->u.SetIRQ.iLevel = iLevel;
90
91 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
92 }
93 else
94 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
95 }
96
97 LogFlow(("pdmRCDevHlp_PCISetIrq: caller=%p/%d: returns void\n", pDevIns, pDevIns->iInstance));
98}
99
100
101/** @interface_method_impl{PDMDRVHLPRC,pfnPCISetIrq} */
102static DECLCALLBACK(void) pdmRCDevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
103{
104 PDMDEV_ASSERT_DEVINS(pDevIns);
105 LogFlow(("pdmRCDevHlp_ISASetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
106
107 pdmRCIsaSetIrq(pDevIns->Internal.s.pVMRC, iIrq, iLevel);
108
109 LogFlow(("pdmRCDevHlp_ISASetIrq: caller=%p/%d: returns void\n", pDevIns, pDevIns->iInstance));
110}
111
112
113/** @interface_method_impl{PDMDEVHLPRC,pfnPhysRead} */
114static DECLCALLBACK(int) pdmRCDevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
115{
116 PDMDEV_ASSERT_DEVINS(pDevIns);
117 LogFlow(("pdmRCDevHlp_PhysRead: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
118 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
119
120 int rc = PGMPhysRead(pDevIns->Internal.s.pVMRC, GCPhys, pvBuf, cbRead);
121 AssertRC(rc); /** @todo track down the users for this bugger. */
122
123 Log(("pdmRCDevHlp_PhysRead: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, rc));
124 return rc;
125}
126
127
128/** @interface_method_impl{PDMDEVHLPRC,pfnPhysWrite} */
129static DECLCALLBACK(int) pdmRCDevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
130{
131 PDMDEV_ASSERT_DEVINS(pDevIns);
132 LogFlow(("pdmRCDevHlp_PhysWrite: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
133 pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
134
135 int rc = PGMPhysWrite(pDevIns->Internal.s.pVMRC, GCPhys, pvBuf, cbWrite);
136 AssertRC(rc); /** @todo track down the users for this bugger. */
137
138 Log(("pdmRCDevHlp_PhysWrite: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, rc));
139 return rc;
140}
141
142
143/** @interface_method_impl{PDMDEVHLPRC,pfnA20IsEnabled} */
144static DECLCALLBACK(bool) pdmRCDevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
145{
146 PDMDEV_ASSERT_DEVINS(pDevIns);
147 LogFlow(("pdmRCDevHlp_A20IsEnabled: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
148
149 bool fEnabled = PGMPhysIsA20Enabled(VMMGetCpu0(pDevIns->Internal.s.pVMRC));
150
151 Log(("pdmRCDevHlp_A20IsEnabled: caller=%p/%d: returns %RTbool\n", pDevIns, pDevIns->iInstance, fEnabled));
152 return fEnabled;
153}
154
155
156/** @interface_method_impl{PDMDEVHLPRC,pfnVMState} */
157static DECLCALLBACK(VMSTATE) pdmRCDevHlp_VMState(PPDMDEVINS pDevIns)
158{
159 PDMDEV_ASSERT_DEVINS(pDevIns);
160
161 VMSTATE enmVMState = pDevIns->Internal.s.pVMRC->enmVMState;
162
163 LogFlow(("pdmRCDevHlp_VMState: caller=%p/%d: returns %d\n", pDevIns, pDevIns->iInstance, enmVMState));
164 return enmVMState;
165}
166
167
168/** @interface_method_impl{PDMDEVHLPRC,pfnVMSetError} */
169static DECLCALLBACK(int) pdmRCDevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
170{
171 PDMDEV_ASSERT_DEVINS(pDevIns);
172 va_list args;
173 va_start(args, pszFormat);
174 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
175 va_end(args);
176 return rc;
177}
178
179
180/** @interface_method_impl{PDMDEVHLPRC,pfnVMSetErrorV} */
181static DECLCALLBACK(int) pdmRCDevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
182{
183 PDMDEV_ASSERT_DEVINS(pDevIns);
184 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
185 return rc;
186}
187
188
189/** @interface_method_impl{PDMDEVHLPRC,pfnVMSetRuntimeError} */
190static DECLCALLBACK(int) pdmRCDevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
191{
192 PDMDEV_ASSERT_DEVINS(pDevIns);
193 va_list va;
194 va_start(va, pszFormat);
195 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
196 va_end(va);
197 return rc;
198}
199
200
201/** @interface_method_impl{PDMDEVHLPRC,pfnVMSetErrorV} */
202static DECLCALLBACK(int) pdmRCDevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
203{
204 PDMDEV_ASSERT_DEVINS(pDevIns);
205 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
206 return rc;
207}
208
209
210/** @interface_method_impl{PDMDEVHLPRC,pfnPATMSetMMIOPatchInfo} */
211static DECLCALLBACK(int) pdmRCDevHlp_PATMSetMMIOPatchInfo(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPTR pCachedData)
212{
213 PDMDEV_ASSERT_DEVINS(pDevIns);
214 LogFlow(("pdmRCDevHlp_PATMSetMMIOPatchInfo: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
215
216 return PATMSetMMIOPatchInfo(pDevIns->Internal.s.pVMRC, GCPhys, (RTRCPTR)(uintptr_t)pCachedData);
217}
218
219
220/** @interface_method_impl{PDMDEVHLPRC,pfnGetVM} */
221static DECLCALLBACK(PVM) pdmRCDevHlp_GetVM(PPDMDEVINS pDevIns)
222{
223 PDMDEV_ASSERT_DEVINS(pDevIns);
224 LogFlow(("pdmRCDevHlp_GetVM: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
225 return pDevIns->Internal.s.pVMRC;
226}
227
228
229/** @interface_method_impl{PDMDEVHLPRC,pfnGetVMCPU} */
230static DECLCALLBACK(PVMCPU) pdmRCDevHlp_GetVMCPU(PPDMDEVINS pDevIns)
231{
232 PDMDEV_ASSERT_DEVINS(pDevIns);
233 LogFlow(("pdmRCDevHlp_GetVMCPU: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
234 return VMMGetCpu(pDevIns->Internal.s.pVMRC);
235}
236
237
238/**
239 * The Raw-Mode Context Device Helper Callbacks.
240 */
241extern DECLEXPORT(const PDMDEVHLPRC) g_pdmRCDevHlp =
242{
243 PDM_DEVHLPRC_VERSION,
244 pdmRCDevHlp_PCISetIrq,
245 pdmRCDevHlp_ISASetIrq,
246 pdmRCDevHlp_PhysRead,
247 pdmRCDevHlp_PhysWrite,
248 pdmRCDevHlp_A20IsEnabled,
249 pdmRCDevHlp_VMState,
250 pdmRCDevHlp_VMSetError,
251 pdmRCDevHlp_VMSetErrorV,
252 pdmRCDevHlp_VMSetRuntimeError,
253 pdmRCDevHlp_VMSetRuntimeErrorV,
254 pdmRCDevHlp_PATMSetMMIOPatchInfo,
255 pdmRCDevHlp_GetVM,
256 pdmRCDevHlp_GetVMCPU,
257 PDM_DEVHLPRC_VERSION
258};
259
260/** @} */
261
262
263
264
265/** @name PIC RC Helpers
266 * @{
267 */
268
269/** @interface_method_impl{PDMPICHLPGC,pfnSetInterruptFF} */
270static DECLCALLBACK(void) pdmRCPicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
271{
272 PDMDEV_ASSERT_DEVINS(pDevIns);
273 PVM pVM = pDevIns->Internal.s.pVMRC;
274
275 if (pVM->pdm.s.Apic.pfnLocalInterruptRC)
276 {
277 LogFlow(("pdmRCPicHlp_SetInterruptFF: caller='%p'/%d: Setting local interrupt on LAPIC\n",
278 pDevIns, pDevIns->iInstance));
279 /* Raise the LAPIC's LINT0 line instead of signaling the CPU directly. */
280 pVM->pdm.s.Apic.pfnLocalInterruptRC(pVM->pdm.s.Apic.pDevInsRC, 0, 1);
281 return;
282 }
283
284 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
285
286 LogFlow(("pdmRCPicHlp_SetInterruptFF: caller=%p/%d: VMMCPU_FF_INTERRUPT_PIC %d -> 1\n",
287 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_PIC)));
288
289 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC);
290}
291
292
293/** @interface_method_impl{PDMPICHLPGC,pfnClearInterruptFF} */
294static DECLCALLBACK(void) pdmRCPicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
295{
296 PDMDEV_ASSERT_DEVINS(pDevIns);
297 PVM pVM = pDevIns->Internal.s.CTX_SUFF(pVM);
298
299 if (pVM->pdm.s.Apic.pfnLocalInterruptRC)
300 {
301 /* Raise the LAPIC's LINT0 line instead of signaling the CPU directly. */
302 LogFlow(("pdmRCPicHlp_ClearInterruptFF: caller='%s'/%d: Clearing local interrupt on LAPIC\n",
303 pDevIns, pDevIns->iInstance));
304 /* Lower the LAPIC's LINT0 line instead of signaling the CPU directly. */
305 pVM->pdm.s.Apic.pfnLocalInterruptRC(pVM->pdm.s.Apic.pDevInsRC, 0, 0);
306 return;
307 }
308
309 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
310
311 LogFlow(("pdmRCPicHlp_ClearInterruptFF: caller=%p/%d: VMCPU_FF_INTERRUPT_PIC %d -> 0\n",
312 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_PIC)));
313
314 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
315}
316
317
318/** @interface_method_impl{PDMPICHLPGC,pfnLock} */
319static DECLCALLBACK(int) pdmRCPicHlp_Lock(PPDMDEVINS pDevIns, int rc)
320{
321 PDMDEV_ASSERT_DEVINS(pDevIns);
322 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
323}
324
325
326/** @interface_method_impl{PDMPICHLPGC,pfnUnlock} */
327static DECLCALLBACK(void) pdmRCPicHlp_Unlock(PPDMDEVINS pDevIns)
328{
329 PDMDEV_ASSERT_DEVINS(pDevIns);
330 pdmUnlock(pDevIns->Internal.s.pVMRC);
331}
332
333
334/**
335 * The Raw-Mode Context PIC Helper Callbacks.
336 */
337extern DECLEXPORT(const PDMPICHLPRC) g_pdmRCPicHlp =
338{
339 PDM_PICHLPRC_VERSION,
340 pdmRCPicHlp_SetInterruptFF,
341 pdmRCPicHlp_ClearInterruptFF,
342 pdmRCPicHlp_Lock,
343 pdmRCPicHlp_Unlock,
344 PDM_PICHLPRC_VERSION
345};
346
347/** @} */
348
349
350
351
352/** @name APIC RC Helpers
353 * @{
354 */
355
356/** @interface_method_impl{PDMAPICHLPRC,pfnSetInterruptFF} */
357static DECLCALLBACK(void) pdmRCApicHlp_SetInterruptFF(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu)
358{
359 PDMDEV_ASSERT_DEVINS(pDevIns);
360 PVM pVM = pDevIns->Internal.s.pVMRC;
361 PVMCPU pVCpu = &pVM->aCpus[idCpu];
362
363 AssertReturnVoid(idCpu < pVM->cCpus);
364
365 LogFlow(("pdmRCApicHlp_SetInterruptFF: caller=%p/%d: VM_FF_INTERRUPT %d -> 1\n",
366 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_APIC)));
367 switch (enmType)
368 {
369 case PDMAPICIRQ_HARDWARE:
370 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC);
371 break;
372 case PDMAPICIRQ_NMI:
373 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI);
374 break;
375 case PDMAPICIRQ_SMI:
376 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_SMI);
377 break;
378 case PDMAPICIRQ_EXTINT:
379 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC);
380 break;
381 default:
382 AssertMsgFailed(("enmType=%d\n", enmType));
383 break;
384 }
385}
386
387
388/** @interface_method_impl{PDMAPICHLPRC,pfnClearInterruptFF} */
389static DECLCALLBACK(void) pdmRCApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu)
390{
391 PDMDEV_ASSERT_DEVINS(pDevIns);
392 PVM pVM = pDevIns->Internal.s.pVMRC;
393 PVMCPU pVCpu = &pVM->aCpus[idCpu];
394
395 AssertReturnVoid(idCpu < pVM->cCpus);
396
397 LogFlow(("pdmRCApicHlp_ClearInterruptFF: caller=%p/%d: VM_FF_INTERRUPT %d -> 0\n",
398 pDevIns, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_APIC)));
399
400 /* Note: NMI/SMI can't be cleared. */
401 switch (enmType)
402 {
403 case PDMAPICIRQ_HARDWARE:
404 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_APIC);
405 break;
406 case PDMAPICIRQ_EXTINT:
407 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
408 break;
409 default:
410 AssertMsgFailed(("enmType=%d\n", enmType));
411 break;
412 }
413}
414
415
416/** @interface_method_impl{PDMAPICHLPRC,pfnChangeFeature} */
417static DECLCALLBACK(void) pdmRCApicHlp_ChangeFeature(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion)
418{
419 PDMDEV_ASSERT_DEVINS(pDevIns);
420 LogFlow(("pdmRCApicHlp_ChangeFeature: caller=%p/%d: version=%d\n", pDevIns, pDevIns->iInstance, (int)enmVersion));
421 switch (enmVersion)
422 {
423 case PDMAPICVERSION_NONE:
424 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_APIC);
425 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_X2APIC);
426 break;
427 case PDMAPICVERSION_APIC:
428 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_APIC);
429 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_X2APIC);
430 break;
431 case PDMAPICVERSION_X2APIC:
432 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_X2APIC);
433 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMRC, CPUMCPUIDFEATURE_APIC);
434 break;
435 default:
436 AssertMsgFailed(("Unknown APIC version: %d\n", (int)enmVersion));
437 }
438}
439
440
441/** @interface_method_impl{PDMAPICHLPRC,pfnLock} */
442static DECLCALLBACK(int) pdmRCApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
443{
444 PDMDEV_ASSERT_DEVINS(pDevIns);
445 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
446}
447
448
449/** @interface_method_impl{PDMAPICHLPRC,pfnUnlock} */
450static DECLCALLBACK(void) pdmRCApicHlp_Unlock(PPDMDEVINS pDevIns)
451{
452 PDMDEV_ASSERT_DEVINS(pDevIns);
453 pdmUnlock(pDevIns->Internal.s.pVMRC);
454}
455
456
457/** @interface_method_impl{PDMAPICHLPRC,pfnGetCpuId} */
458static DECLCALLBACK(VMCPUID) pdmRCApicHlp_GetCpuId(PPDMDEVINS pDevIns)
459{
460 PDMDEV_ASSERT_DEVINS(pDevIns);
461 return VMMGetCpuId(pDevIns->Internal.s.pVMRC);
462}
463
464
465/**
466 * The Raw-Mode Context APIC Helper Callbacks.
467 */
468extern DECLEXPORT(const PDMAPICHLPRC) g_pdmRCApicHlp =
469{
470 PDM_APICHLPRC_VERSION,
471 pdmRCApicHlp_SetInterruptFF,
472 pdmRCApicHlp_ClearInterruptFF,
473 pdmRCApicHlp_ChangeFeature,
474 pdmRCApicHlp_Lock,
475 pdmRCApicHlp_Unlock,
476 pdmRCApicHlp_GetCpuId,
477 PDM_APICHLPRC_VERSION
478};
479
480/** @} */
481
482
483
484
485/** @name I/O APIC RC Helpers
486 * @{
487 */
488
489/** @interface_method_impl{PDMIOAPICHLPRC,pfnApicBusDeliver} */
490static DECLCALLBACK(int) pdmRCIoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
491 uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode)
492{
493 PDMDEV_ASSERT_DEVINS(pDevIns);
494 PVM pVM = pDevIns->Internal.s.pVMRC;
495 LogFlow(("pdmRCIoApicHlp_ApicBusDeliver: caller=%p/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8\n",
496 pDevIns, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode));
497 if (pVM->pdm.s.Apic.pfnBusDeliverRC)
498 return pVM->pdm.s.Apic.pfnBusDeliverRC(pVM->pdm.s.Apic.pDevInsRC, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode);
499 return VINF_SUCCESS;
500}
501
502
503/** @interface_method_impl{PDMIOAPICHLPRC,pfnLock} */
504static DECLCALLBACK(int) pdmRCIoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
505{
506 PDMDEV_ASSERT_DEVINS(pDevIns);
507 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
508}
509
510
511/** @interface_method_impl{PDMIOAPICHLPRC,pfnUnlock} */
512static DECLCALLBACK(void) pdmRCIoApicHlp_Unlock(PPDMDEVINS pDevIns)
513{
514 PDMDEV_ASSERT_DEVINS(pDevIns);
515 pdmUnlock(pDevIns->Internal.s.pVMRC);
516}
517
518
519/**
520 * The Raw-Mode Context I/O APIC Helper Callbacks.
521 */
522extern DECLEXPORT(const PDMIOAPICHLPRC) g_pdmRCIoApicHlp =
523{
524 PDM_IOAPICHLPRC_VERSION,
525 pdmRCIoApicHlp_ApicBusDeliver,
526 pdmRCIoApicHlp_Lock,
527 pdmRCIoApicHlp_Unlock,
528 PDM_IOAPICHLPRC_VERSION
529};
530
531/** @} */
532
533
534
535
536/** @name PCI Bus RC Helpers
537 * @{
538 */
539
540/** @interface_method_impl{PDMPCIHLPRC,pfnIsaSetIrq} */
541static DECLCALLBACK(void) pdmRCPciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
542{
543 PDMDEV_ASSERT_DEVINS(pDevIns);
544 Log4(("pdmRCPciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
545 pdmRCIsaSetIrq(pDevIns->Internal.s.pVMRC, iIrq, iLevel);
546}
547
548
549/** @interface_method_impl{PDMPCIHLPRC,pfnIoApicSetIrq} */
550static DECLCALLBACK(void) pdmRCPciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
551{
552 PDMDEV_ASSERT_DEVINS(pDevIns);
553 Log4(("pdmRCPciHlp_IoApicSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
554 pdmRCIoApicSetIrq(pDevIns->Internal.s.pVMRC, iIrq, iLevel);
555}
556
557/** @interface_method_impl{PDMPCIHLPRC,pfnIoApicSendMsi} */
558static DECLCALLBACK(void) pdmRCPciHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCAddr, uint32_t uValue)
559{
560 PDMDEV_ASSERT_DEVINS(pDevIns);
561 Log4(("pdmRCPciHlp_IoApicSendMsi: Address=%p Value=%d\n", GCAddr, uValue));
562 pdmRCIoApicSendMsi(pDevIns->Internal.s.pVMRC, GCAddr, uValue);
563}
564
565
566/** @interface_method_impl{PDMPCIHLPRC,pfnLock} */
567static DECLCALLBACK(int) pdmRCPciHlp_Lock(PPDMDEVINS pDevIns, int rc)
568{
569 PDMDEV_ASSERT_DEVINS(pDevIns);
570 return pdmLockEx(pDevIns->Internal.s.pVMRC, rc);
571}
572
573
574/** @interface_method_impl{PDMPCIHLPRC,pfnUnlock} */
575static DECLCALLBACK(void) pdmRCPciHlp_Unlock(PPDMDEVINS pDevIns)
576{
577 PDMDEV_ASSERT_DEVINS(pDevIns);
578 pdmUnlock(pDevIns->Internal.s.pVMRC);
579}
580
581
582/**
583 * The Raw-Mode Context PCI Bus Helper Callbacks.
584 */
585extern DECLEXPORT(const PDMPCIHLPRC) g_pdmRCPciHlp =
586{
587 PDM_PCIHLPRC_VERSION,
588 pdmRCPciHlp_IsaSetIrq,
589 pdmRCPciHlp_IoApicSetIrq,
590 pdmRCPciHlp_IoApicSendMsi,
591 pdmRCPciHlp_Lock,
592 pdmRCPciHlp_Unlock,
593 PDM_PCIHLPRC_VERSION, /* the end */
594};
595
596/** @} */
597
598
599
600
601/** @name HPET RC Helpers
602 * @{
603 */
604
605
606/**
607 * The Raw-Mode Context HPET Helper Callbacks.
608 */
609extern DECLEXPORT(const PDMHPETHLPRC) g_pdmRCHpetHlp =
610{
611 PDM_HPETHLPRC_VERSION,
612 PDM_HPETHLPRC_VERSION, /* the end */
613};
614
615/** @} */
616
617
618
619
620/** @name Raw-Mode Context Driver Helpers
621 * @{
622 */
623
624/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetError} */
625static DECLCALLBACK(int) pdmRCDrvHlp_VMSetError(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
626{
627 PDMDRV_ASSERT_DRVINS(pDrvIns);
628 va_list args;
629 va_start(args, pszFormat);
630 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
631 va_end(args);
632 return rc;
633}
634
635
636/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetErrorV} */
637static DECLCALLBACK(int) pdmRCDrvHlp_VMSetErrorV(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
638{
639 PDMDRV_ASSERT_DRVINS(pDrvIns);
640 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMRC, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
641 return rc;
642}
643
644
645/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetRuntimeError} */
646static DECLCALLBACK(int) pdmRCDrvHlp_VMSetRuntimeError(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
647{
648 PDMDRV_ASSERT_DRVINS(pDrvIns);
649 va_list va;
650 va_start(va, pszFormat);
651 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
652 va_end(va);
653 return rc;
654}
655
656
657/** @interface_method_impl{PDMDRVHLPRC,pfnVMSetErrorV} */
658static DECLCALLBACK(int) pdmRCDrvHlp_VMSetRuntimeErrorV(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
659{
660 PDMDRV_ASSERT_DRVINS(pDrvIns);
661 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVMRC, fFlags, pszErrorId, pszFormat, va);
662 return rc;
663}
664
665
666/** @interface_method_impl{PDMDRVHLPRC,pfnAssertEMT} */
667static DECLCALLBACK(bool) pdmRCDrvHlp_AssertEMT(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
668{
669 PDMDRV_ASSERT_DRVINS(pDrvIns);
670 if (VM_IS_EMT(pDrvIns->Internal.s.pVMRC))
671 return true;
672
673 RTAssertMsg1Weak("AssertEMT", iLine, pszFile, pszFunction);
674 RTAssertPanic();
675 return false;
676}
677
678
679/** @interface_method_impl{PDMDRVHLPRC,pfnAssertOther} */
680static DECLCALLBACK(bool) pdmRCDrvHlp_AssertOther(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
681{
682 PDMDRV_ASSERT_DRVINS(pDrvIns);
683 if (!VM_IS_EMT(pDrvIns->Internal.s.pVMRC))
684 return true;
685
686 /* Note: While we don't have any other threads but EMT(0) in RC, might
687 still have drive code compiled in which it shouldn't execute. */
688 RTAssertMsg1Weak("AssertOther", iLine, pszFile, pszFunction);
689 RTAssertPanic();
690 return false;
691}
692
693
694/** @interface_method_impl{PDMDRVHLPRC,pfnFTSetCheckpoint} */
695static DECLCALLBACK(int) pdmRCDrvHlp_FTSetCheckpoint(PPDMDRVINS pDrvIns, FTMCHECKPOINTTYPE enmType)
696{
697 PDMDRV_ASSERT_DRVINS(pDrvIns);
698 return FTMSetCheckpoint(pDrvIns->Internal.s.pVMRC, enmType);
699}
700
701
702/**
703 * The Raw-Mode Context Driver Helper Callbacks.
704 */
705extern DECLEXPORT(const PDMDRVHLPRC) g_pdmRCDrvHlp =
706{
707 PDM_DRVHLPRC_VERSION,
708 pdmRCDrvHlp_VMSetError,
709 pdmRCDrvHlp_VMSetErrorV,
710 pdmRCDrvHlp_VMSetRuntimeError,
711 pdmRCDrvHlp_VMSetRuntimeErrorV,
712 pdmRCDrvHlp_AssertEMT,
713 pdmRCDrvHlp_AssertOther,
714 pdmRCDrvHlp_FTSetCheckpoint,
715 PDM_DRVHLPRC_VERSION
716};
717
718/** @} */
719
720
721
722
723/**
724 * Sets an irq on the I/O APIC.
725 *
726 * @param pVM The VM handle.
727 * @param iIrq The irq.
728 * @param iLevel The new level.
729 */
730static void pdmRCIsaSetIrq(PVM pVM, int iIrq, int iLevel)
731{
732 if ( ( pVM->pdm.s.IoApic.pDevInsRC
733 || !pVM->pdm.s.IoApic.pDevInsR3)
734 && ( pVM->pdm.s.Pic.pDevInsRC
735 || !pVM->pdm.s.Pic.pDevInsR3))
736 {
737 pdmLock(pVM);
738 if (pVM->pdm.s.Pic.pDevInsRC)
739 pVM->pdm.s.Pic.pfnSetIrqRC(pVM->pdm.s.Pic.pDevInsRC, iIrq, iLevel);
740 if (pVM->pdm.s.IoApic.pDevInsRC)
741 pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel);
742 pdmUnlock(pVM);
743 }
744 else
745 {
746 /* queue for ring-3 execution. */
747 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
748 if (pTask)
749 {
750 pTask->enmOp = PDMDEVHLPTASKOP_ISA_SET_IRQ;
751 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
752 pTask->u.SetIRQ.iIrq = iIrq;
753 pTask->u.SetIRQ.iLevel = iLevel;
754
755 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
756 }
757 else
758 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
759 }
760}
761
762
763/**
764 * Sets an irq on the I/O APIC.
765 *
766 * @param pVM The VM handle.
767 * @param iIrq The irq.
768 * @param iLevel The new level.
769 */
770static void pdmRCIoApicSetIrq(PVM pVM, int iIrq, int iLevel)
771{
772 if (pVM->pdm.s.IoApic.pDevInsRC)
773 {
774 pdmLock(pVM);
775 pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel);
776 pdmUnlock(pVM);
777 }
778 else if (pVM->pdm.s.IoApic.pDevInsR3)
779 {
780 /* queue for ring-3 execution. */
781 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC);
782 if (pTask)
783 {
784 pTask->enmOp = PDMDEVHLPTASKOP_IOAPIC_SET_IRQ;
785 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */
786 pTask->u.SetIRQ.iIrq = iIrq;
787 pTask->u.SetIRQ.iLevel = iLevel;
788
789 PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0);
790 }
791 else
792 AssertMsgFailed(("We're out of devhlp queue items!!!\n"));
793 }
794}
795
796
797/**
798 * Sends an MSI to I/O APIC.
799 *
800 * @param pVM The VM handle.
801 * @param GCAddr Address of the message.
802 * @param uValue Value of the message.
803 */
804static void pdmRCIoApicSendMsi(PVM pVM, RTGCPHYS GCAddr, uint32_t uValue)
805{
806 if (pVM->pdm.s.IoApic.pDevInsRC)
807 {
808 pdmLock(pVM);
809 pVM->pdm.s.IoApic.pfnSendMsiRC(pVM->pdm.s.IoApic.pDevInsRC, GCAddr, uValue);
810 pdmUnlock(pVM);
811 }
812}
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