VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/PDMDevMiscHlp.cpp@ 40923

Last change on this file since 40923 was 40907, checked in by vboxsync, 13 years ago

Working on tracking IRQs for tracing and logging purposes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 24.8 KB
Line 
1/* $Id: PDMDevMiscHlp.cpp 40907 2012-04-13 20:50:14Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, Misc. Device Helpers.
4 */
5
6/*
7 * Copyright (C) 2006-2012 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/vmm/pdm.h>
25#include <VBox/vmm/pgm.h>
26#ifdef VBOX_WITH_REM
27# include <VBox/vmm/rem.h>
28#endif
29#include <VBox/vmm/vm.h>
30#include <VBox/vmm/vmm.h>
31
32#include <VBox/log.h>
33#include <VBox/err.h>
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/thread.h>
37
38
39#include "PDMInline.h"
40#include "dtrace/VBoxVMM.h"
41
42
43
44/** @name Ring-3 PIC Helpers
45 * @{
46 */
47
48/** @interface_method_impl{PDMPICHLPR3,pfnSetInterruptFF} */
49static DECLCALLBACK(void) pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
50{
51 PDMDEV_ASSERT_DEVINS(pDevIns);
52 PVM pVM = pDevIns->Internal.s.pVMR3;
53
54 if (pVM->pdm.s.Apic.pfnLocalInterruptR3)
55 {
56 LogFlow(("pdmR3PicHlp_SetInterruptFF: caller='%s'/%d: Setting local interrupt on LAPIC\n",
57 pDevIns->pReg->szName, pDevIns->iInstance));
58 /* Raise the LAPIC's LINT0 line instead of signaling the CPU directly. */
59 pVM->pdm.s.Apic.pfnLocalInterruptR3(pVM->pdm.s.Apic.pDevInsR3, 0, 1);
60 return;
61 }
62
63 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
64
65 LogFlow(("pdmR3PicHlp_SetInterruptFF: caller='%s'/%d: VMCPU_FF_INTERRUPT_PIC %d -> 1\n",
66 pDevIns->pReg->szName, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_PIC)));
67
68 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC);
69#ifdef VBOX_WITH_REM
70 REMR3NotifyInterruptSet(pVM, pVCpu);
71#endif
72 VMR3NotifyCpuFFU(pVCpu->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM | VMNOTIFYFF_FLAGS_POKE);
73}
74
75
76/** @interface_method_impl{PDMPICHLPR3,pfnClearInterruptFF} */
77static DECLCALLBACK(void) pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
78{
79 PDMDEV_ASSERT_DEVINS(pDevIns);
80 PVM pVM = pDevIns->Internal.s.pVMR3;
81 PVMCPU pVCpu = &pVM->aCpus[0]; /* for PIC we always deliver to CPU 0, MP use APIC */
82
83 if (pVM->pdm.s.Apic.pfnLocalInterruptR3)
84 {
85 /* Raise the LAPIC's LINT0 line instead of signaling the CPU directly. */
86 LogFlow(("pdmR3PicHlp_ClearInterruptFF: caller='%s'/%d: Clearing local interrupt on LAPIC\n",
87 pDevIns->pReg->szName, pDevIns->iInstance));
88 /* Lower the LAPIC's LINT0 line instead of signaling the CPU directly. */
89 pVM->pdm.s.Apic.pfnLocalInterruptR3(pVM->pdm.s.Apic.pDevInsR3, 0, 0);
90 return;
91 }
92
93 LogFlow(("pdmR3PicHlp_ClearInterruptFF: caller='%s'/%d: VMCPU_FF_INTERRUPT_PIC %d -> 0\n",
94 pDevIns->pReg->szName, pDevIns->iInstance, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_PIC)));
95
96 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
97#ifdef VBOX_WITH_REM
98 REMR3NotifyInterruptClear(pVM, pVCpu);
99#endif
100}
101
102
103/** @interface_method_impl{PDMPICHLPR3,pfnLock} */
104static DECLCALLBACK(int) pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
105{
106 PDMDEV_ASSERT_DEVINS(pDevIns);
107 return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
108}
109
110
111/** @interface_method_impl{PDMPICHLPR3,pfnUnlock} */
112static DECLCALLBACK(void) pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns)
113{
114 PDMDEV_ASSERT_DEVINS(pDevIns);
115 pdmUnlock(pDevIns->Internal.s.pVMR3);
116}
117
118
119/** @interface_method_impl{PDMPICHLPR3,pfnGetRCHelpers} */
120static DECLCALLBACK(PCPDMPICHLPRC) pdmR3PicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
121{
122 PDMDEV_ASSERT_DEVINS(pDevIns);
123 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
124 RTRCPTR pRCHelpers = 0;
125 int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCPicHlp", &pRCHelpers);
126 AssertReleaseRC(rc);
127 AssertRelease(pRCHelpers);
128 LogFlow(("pdmR3PicHlp_GetRCHelpers: caller='%s'/%d: returns %RRv\n",
129 pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
130 return pRCHelpers;
131}
132
133
134/** @interface_method_impl{PDMPICHLPR3,pfnGetR0Helpers} */
135static DECLCALLBACK(PCPDMPICHLPR0) pdmR3PicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
136{
137 PDMDEV_ASSERT_DEVINS(pDevIns);
138 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
139 PCPDMPICHLPR0 pR0Helpers = 0;
140 int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0PicHlp", &pR0Helpers);
141 AssertReleaseRC(rc);
142 AssertRelease(pR0Helpers);
143 LogFlow(("pdmR3PicHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
144 pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
145 return pR0Helpers;
146}
147
148
149/**
150 * PIC Device Helpers.
151 */
152const PDMPICHLPR3 g_pdmR3DevPicHlp =
153{
154 PDM_PICHLPR3_VERSION,
155 pdmR3PicHlp_SetInterruptFF,
156 pdmR3PicHlp_ClearInterruptFF,
157 pdmR3PicHlp_Lock,
158 pdmR3PicHlp_Unlock,
159 pdmR3PicHlp_GetRCHelpers,
160 pdmR3PicHlp_GetR0Helpers,
161 PDM_PICHLPR3_VERSION /* the end */
162};
163
164/** @} */
165
166
167
168
169/** @name R3 APIC Helpers
170 * @{
171 */
172
173/** @interface_method_impl{PDMAPICHLPR3,pfnSetInterruptFF} */
174static DECLCALLBACK(void) pdmR3ApicHlp_SetInterruptFF(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu)
175{
176 PDMDEV_ASSERT_DEVINS(pDevIns);
177 PVM pVM = pDevIns->Internal.s.pVMR3;
178 PVMCPU pVCpu = &pVM->aCpus[idCpu];
179
180 AssertReturnVoid(idCpu < pVM->cCpus);
181
182 LogFlow(("pdmR3ApicHlp_SetInterruptFF: caller='%s'/%d: VMCPU_FF_INTERRUPT_APIC(%d) %d -> 1\n",
183 pDevIns->pReg->szName, pDevIns->iInstance, idCpu, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_APIC)));
184
185 switch (enmType)
186 {
187 case PDMAPICIRQ_HARDWARE:
188 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC);
189 break;
190 case PDMAPICIRQ_NMI:
191 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI);
192 break;
193 case PDMAPICIRQ_SMI:
194 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_SMI);
195 break;
196 case PDMAPICIRQ_EXTINT:
197 VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC);
198 break;
199 default:
200 AssertMsgFailed(("enmType=%d\n", enmType));
201 break;
202 }
203#ifdef VBOX_WITH_REM
204 REMR3NotifyInterruptSet(pVM, pVCpu);
205#endif
206 VMR3NotifyCpuFFU(pVCpu->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM | VMNOTIFYFF_FLAGS_POKE);
207}
208
209
210/** @interface_method_impl{PDMAPICHLPR3,pfnClearInterruptFF} */
211static DECLCALLBACK(void) pdmR3ApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu)
212{
213 PDMDEV_ASSERT_DEVINS(pDevIns);
214 PVM pVM = pDevIns->Internal.s.pVMR3;
215 PVMCPU pVCpu = &pVM->aCpus[idCpu];
216
217 AssertReturnVoid(idCpu < pVM->cCpus);
218
219 LogFlow(("pdmR3ApicHlp_ClearInterruptFF: caller='%s'/%d: VMCPU_FF_INTERRUPT_APIC(%d) %d -> 0\n",
220 pDevIns->pReg->szName, pDevIns->iInstance, idCpu, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_APIC)));
221
222 /* Note: NMI/SMI can't be cleared. */
223 switch (enmType)
224 {
225 case PDMAPICIRQ_HARDWARE:
226 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_APIC);
227 break;
228 case PDMAPICIRQ_EXTINT:
229 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
230 break;
231 default:
232 AssertMsgFailed(("enmType=%d\n", enmType));
233 break;
234 }
235#ifdef VBOX_WITH_REM
236 REMR3NotifyInterruptClear(pVM, pVCpu);
237#endif
238}
239
240
241/** @interface_method_impl{PDMAPICHLPR3,pfnChangeFeature} */
242static DECLCALLBACK(void) pdmR3ApicHlp_ChangeFeature(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion)
243{
244 PDMDEV_ASSERT_DEVINS(pDevIns);
245 LogFlow(("pdmR3ApicHlp_ChangeFeature: caller='%s'/%d: version=%d\n",
246 pDevIns->pReg->szName, pDevIns->iInstance, (int)enmVersion));
247 switch (enmVersion)
248 {
249 case PDMAPICVERSION_NONE:
250 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_APIC);
251 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_X2APIC);
252 break;
253 case PDMAPICVERSION_APIC:
254 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_APIC);
255 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_X2APIC);
256 break;
257 case PDMAPICVERSION_X2APIC:
258 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_X2APIC);
259 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_APIC);
260 break;
261 default:
262 AssertMsgFailed(("Unknown APIC version: %d\n", (int)enmVersion));
263 }
264}
265
266/** @interface_method_impl{PDMAPICHLPR3,pfnGetCpuId} */
267static DECLCALLBACK(VMCPUID) pdmR3ApicHlp_GetCpuId(PPDMDEVINS pDevIns)
268{
269 PDMDEV_ASSERT_DEVINS(pDevIns);
270 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
271 return VMMGetCpuId(pDevIns->Internal.s.pVMR3);
272}
273
274
275/** @interface_method_impl{PDMAPICHLPR3,pfnSendSipi} */
276static DECLCALLBACK(void) pdmR3ApicHlp_SendSipi(PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t uVector)
277{
278 PDMDEV_ASSERT_DEVINS(pDevIns);
279 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
280 VMMR3SendSipi(pDevIns->Internal.s.pVMR3, idCpu, uVector);
281}
282
283/** @interface_method_impl{PDMAPICHLPR3,pfnSendInitIpi} */
284static DECLCALLBACK(void) pdmR3ApicHlp_SendInitIpi(PPDMDEVINS pDevIns, VMCPUID idCpu)
285{
286 PDMDEV_ASSERT_DEVINS(pDevIns);
287 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
288 VMMR3SendInitIpi(pDevIns->Internal.s.pVMR3, idCpu);
289}
290
291/** @interface_method_impl{PDMAPICHLPR3,pfnGetRCHelpers} */
292static DECLCALLBACK(PCPDMAPICHLPRC) pdmR3ApicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
293{
294 PDMDEV_ASSERT_DEVINS(pDevIns);
295 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
296 RTRCPTR pRCHelpers = 0;
297 int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCApicHlp", &pRCHelpers);
298 AssertReleaseRC(rc);
299 AssertRelease(pRCHelpers);
300 LogFlow(("pdmR3ApicHlp_GetRCHelpers: caller='%s'/%d: returns %RRv\n",
301 pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
302 return pRCHelpers;
303}
304
305
306/** @interface_method_impl{PDMAPICHLPR3,pfnGetR0Helpers} */
307static DECLCALLBACK(PCPDMAPICHLPR0) pdmR3ApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
308{
309 PDMDEV_ASSERT_DEVINS(pDevIns);
310 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
311 PCPDMAPICHLPR0 pR0Helpers = 0;
312 int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0ApicHlp", &pR0Helpers);
313 AssertReleaseRC(rc);
314 AssertRelease(pR0Helpers);
315 LogFlow(("pdmR3ApicHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
316 pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
317 return pR0Helpers;
318}
319
320
321/** @interface_method_impl{PDMAPICHLPR3,pfnGetR3CritSect} */
322static DECLCALLBACK(R3PTRTYPE(PPDMCRITSECT)) pdmR3ApicHlp_GetR3CritSect(PPDMDEVINS pDevIns)
323{
324 PDMDEV_ASSERT_DEVINS(pDevIns);
325 LogFlow(("pdmR3ApicHlp_Lock: caller='%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
326 return &pDevIns->Internal.s.pVMR3->pdm.s.CritSect;
327}
328
329
330/** @interface_method_impl{PDMAPICHLPR3,pfnGetRCCritSect} */
331static DECLCALLBACK(RCPTRTYPE(PPDMCRITSECT)) pdmR3ApicHlp_GetRCCritSect(PPDMDEVINS pDevIns)
332{
333 PDMDEV_ASSERT_DEVINS(pDevIns);
334 PVM pVM = pDevIns->Internal.s.pVMR3;
335 RTRCPTR RCPtr = MMHyperCCToRC(pVM, &pVM->pdm.s.CritSect);
336 LogFlow(("pdmR3ApicHlp_GetR0CritSect: caller='%s'/%d: return %RRv\n", pDevIns->pReg->szName, pDevIns->iInstance, RCPtr));
337 return RCPtr;
338}
339
340
341/** @interface_method_impl{PDMAPICHLPR3,pfnGetR3CritSect} */
342static DECLCALLBACK(R0PTRTYPE(PPDMCRITSECT)) pdmR3ApicHlp_GetR0CritSect(PPDMDEVINS pDevIns)
343{
344 PDMDEV_ASSERT_DEVINS(pDevIns);
345 PVM pVM = pDevIns->Internal.s.pVMR3;
346 RTR0PTR R0Ptr = MMHyperCCToR0(pVM, &pVM->pdm.s.CritSect);
347 LogFlow(("pdmR3ApicHlp_GetR0CritSect: caller='%s'/%d: return %RHv\n", pDevIns->pReg->szName, pDevIns->iInstance, R0Ptr));
348 return R0Ptr;
349}
350
351
352
353/**
354 * APIC Device Helpers.
355 */
356const PDMAPICHLPR3 g_pdmR3DevApicHlp =
357{
358 PDM_APICHLPR3_VERSION,
359 pdmR3ApicHlp_SetInterruptFF,
360 pdmR3ApicHlp_ClearInterruptFF,
361 pdmR3ApicHlp_ChangeFeature,
362 pdmR3ApicHlp_GetCpuId,
363 pdmR3ApicHlp_SendSipi,
364 pdmR3ApicHlp_SendInitIpi,
365 pdmR3ApicHlp_GetRCHelpers,
366 pdmR3ApicHlp_GetR0Helpers,
367 pdmR3ApicHlp_GetR3CritSect,
368 pdmR3ApicHlp_GetRCCritSect,
369 pdmR3ApicHlp_GetR0CritSect,
370 PDM_APICHLPR3_VERSION /* the end */
371};
372
373/** @} */
374
375
376
377
378/** @name Ring-3 I/O APIC Helpers
379 * @{
380 */
381
382/** @interface_method_impl{PDMIOAPICHLPR3,pfnApicBusDeliver} */
383static DECLCALLBACK(int) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
384 uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc)
385{
386 PDMDEV_ASSERT_DEVINS(pDevIns);
387 PVM pVM = pDevIns->Internal.s.pVMR3;
388 LogFlow(("pdmR3IoApicHlp_ApicBusDeliver: caller='%s'/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8 uTagSrc=%#x\n",
389 pDevIns->pReg->szName, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode, uTagSrc));
390 if (pVM->pdm.s.Apic.pfnBusDeliverR3)
391 return pVM->pdm.s.Apic.pfnBusDeliverR3(pVM->pdm.s.Apic.pDevInsR3, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode, uTagSrc);
392 return VINF_SUCCESS;
393}
394
395
396/** @interface_method_impl{PDMIOAPICHLPR3,pfnLock} */
397static DECLCALLBACK(int) pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
398{
399 PDMDEV_ASSERT_DEVINS(pDevIns);
400 LogFlow(("pdmR3IoApicHlp_Lock: caller='%s'/%d: rc=%Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
401 return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
402}
403
404
405/** @interface_method_impl{PDMIOAPICHLPR3,pfnUnlock} */
406static DECLCALLBACK(void) pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns)
407{
408 PDMDEV_ASSERT_DEVINS(pDevIns);
409 LogFlow(("pdmR3IoApicHlp_Unlock: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
410 pdmUnlock(pDevIns->Internal.s.pVMR3);
411}
412
413
414/** @interface_method_impl{PDMIOAPICHLPR3,pfnGetRCHelpers} */
415static DECLCALLBACK(PCPDMIOAPICHLPRC) pdmR3IoApicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
416{
417 PDMDEV_ASSERT_DEVINS(pDevIns);
418 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
419 RTRCPTR pRCHelpers = 0;
420 int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCIoApicHlp", &pRCHelpers);
421 AssertReleaseRC(rc);
422 AssertRelease(pRCHelpers);
423 LogFlow(("pdmR3IoApicHlp_GetRCHelpers: caller='%s'/%d: returns %RRv\n",
424 pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
425 return pRCHelpers;
426}
427
428
429/** @interface_method_impl{PDMIOAPICHLPR3,pfnGetR0Helpers} */
430static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
431{
432 PDMDEV_ASSERT_DEVINS(pDevIns);
433 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
434 PCPDMIOAPICHLPR0 pR0Helpers = 0;
435 int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0IoApicHlp", &pR0Helpers);
436 AssertReleaseRC(rc);
437 AssertRelease(pR0Helpers);
438 LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
439 pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
440 return pR0Helpers;
441}
442
443
444/**
445 * I/O APIC Device Helpers.
446 */
447const PDMIOAPICHLPR3 g_pdmR3DevIoApicHlp =
448{
449 PDM_IOAPICHLPR3_VERSION,
450 pdmR3IoApicHlp_ApicBusDeliver,
451 pdmR3IoApicHlp_Lock,
452 pdmR3IoApicHlp_Unlock,
453 pdmR3IoApicHlp_GetRCHelpers,
454 pdmR3IoApicHlp_GetR0Helpers,
455 PDM_IOAPICHLPR3_VERSION /* the end */
456};
457
458/** @} */
459
460
461
462
463/** @name Ring-3 PCI Bus Helpers
464 * @{
465 */
466
467/** @interface_method_impl{PDMPCIHLPR3,pfnIsaSetIrq} */
468static DECLCALLBACK(void) pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
469{
470 PDMDEV_ASSERT_DEVINS(pDevIns);
471 Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
472 PVM pVM = pDevIns->Internal.s.pVMR3;
473 PDMIsaSetIrq(pDevIns->Internal.s.pVMR3, iIrq, iLevel, uTagSrc);
474}
475
476/** @interface_method_impl{PDMPCIHLPR3,pfnIoApicSetIrq} */
477static DECLCALLBACK(void) pdmR3PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
478{
479 PDMDEV_ASSERT_DEVINS(pDevIns);
480 Log4(("pdmR3PciHlp_IoApicSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
481 PDMIoApicSetIrq(pDevIns->Internal.s.pVMR3, iIrq, iLevel, uTagSrc);
482}
483
484/** @interface_method_impl{PDMPCIHLPR3,pfnIoApicSendMsi} */
485static DECLCALLBACK(void) pdmR3PciHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCAddr, uint32_t uValue, uint32_t uTagSrc)
486{
487 PDMDEV_ASSERT_DEVINS(pDevIns);
488 Log4(("pdmR3PciHlp_IoApicSendMsi: address=%p value=%x uTagSrc=%#x\n", GCAddr, uValue, uTagSrc));
489 PDMIoApicSendMsi(pDevIns->Internal.s.pVMR3, GCAddr, uValue, uTagSrc);
490}
491
492/** @interface_method_impl{PDMPCIHLPR3,pfnIsMMIO2Base} */
493static DECLCALLBACK(bool) pdmR3PciHlp_IsMMIO2Base(PPDMDEVINS pDevIns, PPDMDEVINS pOwner, RTGCPHYS GCPhys)
494{
495 PDMDEV_ASSERT_DEVINS(pDevIns);
496 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
497 bool fRc = PGMR3PhysMMIO2IsBase(pDevIns->Internal.s.pVMR3, pOwner, GCPhys);
498 Log4(("pdmR3PciHlp_IsMMIO2Base: pOwner=%p GCPhys=%RGp -> %RTbool\n", pOwner, GCPhys, fRc));
499 return fRc;
500}
501
502
503/** @interface_method_impl{PDMPCIHLPR3,pfnLock} */
504static DECLCALLBACK(int) pdmR3PciHlp_Lock(PPDMDEVINS pDevIns, int rc)
505{
506 PDMDEV_ASSERT_DEVINS(pDevIns);
507 LogFlow(("pdmR3PciHlp_Lock: caller='%s'/%d: rc=%Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
508 return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
509}
510
511
512/** @interface_method_impl{PDMPCIHLPR3,pfnUnlock} */
513static DECLCALLBACK(void) pdmR3PciHlp_Unlock(PPDMDEVINS pDevIns)
514{
515 PDMDEV_ASSERT_DEVINS(pDevIns);
516 LogFlow(("pdmR3PciHlp_Unlock: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
517 pdmUnlock(pDevIns->Internal.s.pVMR3);
518}
519
520
521/** @interface_method_impl{PDMPCIHLPR3,pfnGetRCHelpers} */
522static DECLCALLBACK(PCPDMPCIHLPRC) pdmR3PciHlp_GetRCHelpers(PPDMDEVINS pDevIns)
523{
524 PDMDEV_ASSERT_DEVINS(pDevIns);
525 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
526 RTRCPTR pRCHelpers = 0;
527 int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCPciHlp", &pRCHelpers);
528 AssertReleaseRC(rc);
529 AssertRelease(pRCHelpers);
530 LogFlow(("pdmR3IoApicHlp_GetGCHelpers: caller='%s'/%d: returns %RRv\n",
531 pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
532 return pRCHelpers;
533}
534
535
536/** @interface_method_impl{PDMPCIHLPR3,pfnGetR0Helpers} */
537static DECLCALLBACK(PCPDMPCIHLPR0) pdmR3PciHlp_GetR0Helpers(PPDMDEVINS pDevIns)
538{
539 PDMDEV_ASSERT_DEVINS(pDevIns);
540 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
541 PCPDMPCIHLPR0 pR0Helpers = 0;
542 int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0PciHlp", &pR0Helpers);
543 AssertReleaseRC(rc);
544 AssertRelease(pR0Helpers);
545 LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
546 pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
547 return pR0Helpers;
548}
549
550
551/**
552 * PCI Bus Device Helpers.
553 */
554const PDMPCIHLPR3 g_pdmR3DevPciHlp =
555{
556 PDM_PCIHLPR3_VERSION,
557 pdmR3PciHlp_IsaSetIrq,
558 pdmR3PciHlp_IoApicSetIrq,
559 pdmR3PciHlp_IoApicSendMsi,
560 pdmR3PciHlp_IsMMIO2Base,
561 pdmR3PciHlp_GetRCHelpers,
562 pdmR3PciHlp_GetR0Helpers,
563 pdmR3PciHlp_Lock,
564 pdmR3PciHlp_Unlock,
565 PDM_PCIHLPR3_VERSION, /* the end */
566};
567
568/** @} */
569
570
571
572
573/** @name Ring-3 HPET Helpers
574 * {@
575 */
576
577/** @interface_method_impl{PDMHPETHLPR3,pfnSetLegacyMode} */
578static DECLCALLBACK(int) pdmR3HpetHlp_SetLegacyMode(PPDMDEVINS pDevIns, bool fActivated)
579{
580 PDMDEV_ASSERT_DEVINS(pDevIns);
581 LogFlow(("pdmR3HpetHlp_SetLegacyMode: caller='%s'/%d: fActivated=%RTbool\n", pDevIns->pReg->szName, pDevIns->iInstance, fActivated));
582
583 size_t i;
584 int rc = VINF_SUCCESS;
585 static const char * const s_apszDevsToNotify[] =
586 {
587 "i8254",
588 "mc146818"
589 };
590 for (i = 0; i < RT_ELEMENTS(s_apszDevsToNotify); i++)
591 {
592 PPDMIBASE pBase;
593 rc = PDMR3QueryDevice(pDevIns->Internal.s.pVMR3, "i8254", 0, &pBase);
594 if (RT_SUCCESS(rc))
595 {
596 PPDMIHPETLEGACYNOTIFY pPort = PDMIBASE_QUERY_INTERFACE(pBase, PDMIHPETLEGACYNOTIFY);
597 AssertLogRelMsgBreakStmt(pPort, ("%s\n", s_apszDevsToNotify[i]), rc = VERR_PDM_HPET_LEGACY_NOTIFY_MISSING);
598 pPort->pfnModeChanged(pPort, fActivated);
599 }
600 else if ( rc == VERR_PDM_DEVICE_NOT_FOUND
601 || rc == VERR_PDM_DEVICE_INSTANCE_NOT_FOUND)
602 rc = VINF_SUCCESS; /* the device isn't configured, ignore. */
603 else
604 AssertLogRelMsgFailedBreak(("%s -> %Rrc\n", s_apszDevsToNotify[i], rc));
605 }
606
607 /* Don't bother cleaning up, any failure here will cause a guru meditation. */
608
609 LogFlow(("pdmR3HpetHlp_SetLegacyMode: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
610 return rc;
611}
612
613
614/** @interface_method_impl{PDMHPETHLPR3,pfnSetIrq} */
615static DECLCALLBACK(int) pdmR3HpetHlp_SetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
616{
617 PDMDEV_ASSERT_DEVINS(pDevIns);
618 LogFlow(("pdmR3HpetHlp_SetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
619 PVM pVM = pDevIns->Internal.s.pVMR3;
620
621 pdmLock(pVM);
622 uint32_t uTagSrc;
623 if (iLevel & PDM_IRQ_LEVEL_HIGH)
624 {
625 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
626 if (iLevel == PDM_IRQ_LEVEL_HIGH)
627 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
628 else
629 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
630 }
631 else
632 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
633
634 PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */
635
636 if (iLevel == PDM_IRQ_LEVEL_LOW)
637 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
638 pdmUnlock(pVM);
639 return 0;
640}
641
642
643/** @interface_method_impl{PDMHPETHLPR3,pfnGetRCHelpers} */
644static DECLCALLBACK(PCPDMHPETHLPRC) pdmR3HpetHlp_GetRCHelpers(PPDMDEVINS pDevIns)
645{
646 PDMDEV_ASSERT_DEVINS(pDevIns);
647 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
648 RTRCPTR pRCHelpers = 0;
649 int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCHpetHlp", &pRCHelpers);
650 AssertReleaseRC(rc);
651 AssertRelease(pRCHelpers);
652 LogFlow(("pdmR3HpetHlp_GetGCHelpers: caller='%s'/%d: returns %RRv\n",
653 pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
654 return pRCHelpers;
655}
656
657
658/** @interface_method_impl{PDMHPETHLPR3,pfnGetR0Helpers} */
659static DECLCALLBACK(PCPDMHPETHLPR0) pdmR3HpetHlp_GetR0Helpers(PPDMDEVINS pDevIns)
660{
661 PDMDEV_ASSERT_DEVINS(pDevIns);
662 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
663 PCPDMHPETHLPR0 pR0Helpers = 0;
664 int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0HpetHlp", &pR0Helpers);
665 AssertReleaseRC(rc);
666 AssertRelease(pR0Helpers);
667 LogFlow(("pdmR3HpetHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
668 pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
669 return pR0Helpers;
670}
671
672
673/**
674 * HPET Device Helpers.
675 */
676const PDMHPETHLPR3 g_pdmR3DevHpetHlp =
677{
678 PDM_HPETHLPR3_VERSION,
679 pdmR3HpetHlp_GetRCHelpers,
680 pdmR3HpetHlp_GetR0Helpers,
681 pdmR3HpetHlp_SetLegacyMode,
682 pdmR3HpetHlp_SetIrq,
683 PDM_HPETHLPR3_VERSION, /* the end */
684};
685
686/** @} */
687
688
689/** @name Ring-3 Raw PCI Device Helpers
690 * {@
691 */
692
693/** @interface_method_impl{PDMPCIRAWHLPR3,pfnGetRCHelpers} */
694static DECLCALLBACK(PCPDMPCIRAWHLPRC) pdmR3PciRawHlp_GetRCHelpers(PPDMDEVINS pDevIns)
695{
696 PDMDEV_ASSERT_DEVINS(pDevIns);
697 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
698 RTRCPTR pRCHelpers = NIL_RTRCPTR;
699 int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCPciRawHlp", &pRCHelpers);
700 AssertReleaseRC(rc);
701 AssertRelease(pRCHelpers);
702 LogFlow(("pdmR3PciRawHlp_GetGCHelpers: caller='%s'/%d: returns %RRv\n",
703 pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
704 return pRCHelpers;
705}
706
707
708/** @interface_method_impl{PDMPCIRAWHLPR3,pfnGetR0Helpers} */
709static DECLCALLBACK(PCPDMPCIRAWHLPR0) pdmR3PciRawHlp_GetR0Helpers(PPDMDEVINS pDevIns)
710{
711 PDMDEV_ASSERT_DEVINS(pDevIns);
712 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
713 PCPDMHPETHLPR0 pR0Helpers = NIL_RTR0PTR;
714 int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0PciRawHlp", &pR0Helpers);
715 AssertReleaseRC(rc);
716 AssertRelease(pR0Helpers);
717 LogFlow(("pdmR3PciRawHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
718 pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
719 return pR0Helpers;
720}
721
722
723/**
724 * Raw PCI Device Helpers.
725 */
726const PDMPCIRAWHLPR3 g_pdmR3DevPciRawHlp =
727{
728 PDM_PCIRAWHLPR3_VERSION,
729 pdmR3PciRawHlp_GetRCHelpers,
730 pdmR3PciRawHlp_GetR0Helpers,
731 PDM_PCIRAWHLPR3_VERSION, /* the end */
732};
733
734/** @} */
735
736
737/* none yet */
738
739/**
740 * DMAC Device Helpers.
741 */
742const PDMDMACHLP g_pdmR3DevDmacHlp =
743{
744 PDM_DMACHLP_VERSION
745};
746
747
748
749
750/* none yet */
751
752/**
753 * RTC Device Helpers.
754 */
755const PDMRTCHLP g_pdmR3DevRtcHlp =
756{
757 PDM_RTCHLP_VERSION
758};
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette