VirtualBox

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

Last change on this file since 28319 was 28319, checked in by vboxsync, 15 years ago

pdmdev: Made PDMDevHlpVMState available in R0 and RC.

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