VirtualBox

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

Last change on this file since 61705 was 61685, checked in by vboxsync, 9 years ago

VMM: I/O APIC lockless implementation.

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