VirtualBox

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

Last change on this file since 61776 was 61776, checked in by vboxsync, 8 years ago

CPUM,APIC: Per-CPU APIC CPUID feature bit and MSR_IA32_APICBASE GP mask adjustments.

  • Changed the PDMAPICHLPR3::pfnChangeFeature to pfnSetFeatureLevel, removing the RC and R0 versions.
  • Only use pfnSetFeatureLevel from the APIC constructor to communicate to CPUM the max APIC feature level, not to globally flip CPUID[1].EDX[9].
  • Renamed APIC enmOriginalMode to enmMaxMode, changing the type of it and the corresponding config values to PDMAPICMODE. This makes the above simpler and eliminates two conversion functions. It also makes APICMODE private to the APIC again.
  • Introduced CPUMSetGuestCpuIdPerCpuApicFeature for the per-CPU APIC feature bit management.
  • Introduced CPUMCPUIDLEAF_F_CONTAINS_APIC which works same as CPUMCPUIDLEAF_F_CONTAINS_OSXSAVE and CPUMCPUIDLEAF_F_CONTAINS_APIC_ID. Updated existing CPU profiles with this.
  • Made the patch manager helper function actually handle CPUMCPUIDLEAF_F_CONTAINS_APIC and CPUMCPUIDLEAF_F_CONTAINS_OSXSAVE (the latter previously relied on CPUMSetGuestCpuIdFeature/CPUMClearGuestCpuIdFeature from CPUMSetGuestCR4).
  • Pushed CPUMSetGuestCpuIdFeature, CPUMGetGuestCpuIdFeature and CPUMClearGuestCpuIdFeature down to ring-3 only (now CPUMR3*). The latter two function are deprecated.
  • Added call to CPUMSetGuestCpuIdPerCpuApicFeature from load function just in case the APIC is disabled by the guest at the time of saving.
  • CPUMSetGuestCpuIdFeature ensures we've got a MSR_IA32_APICBASE register when enabling the APIC.
  • CPUMSetGuestCpuIdFeature adjust the MSR_IA32_APICBASE GP mask when enabling x2APIC so setting MSR_IA32_APICBASE_EXTD does not trap.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 28.1 KB
Line 
1/* $Id: PDMDevMiscHlp.cpp 61776 2016-06-20 23:25:06Z 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(int) 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 return pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector);
284 }
285#endif
286 return VINF_SUCCESS;
287}
288
289
290/** @interface_method_impl{PDMAPICHLPR3,pfnCalcIrqTag} */
291static DECLCALLBACK(uint32_t) pdmR3ApicHlp_CalcIrqTag(PPDMDEVINS pDevIns, uint8_t u8Level)
292{
293 PDMDEV_ASSERT_DEVINS(pDevIns);
294 PVM pVM = pDevIns->Internal.s.pVMR3;
295 Assert(u8Level == PDM_IRQ_LEVEL_HIGH || u8Level == PDM_IRQ_LEVEL_FLIP_FLOP);
296
297 pdmLock(pVM);
298
299 uint32_t uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
300 if (u8Level == PDM_IRQ_LEVEL_HIGH)
301 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
302 else
303 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
304
305
306 pdmUnlock(pVM);
307 LogFlow(("pdmR3ApicHlp_CalcIrqTag: caller='%s'/%d: returns %#x (u8Level=%d)\n",
308 pDevIns->pReg->szName, pDevIns->iInstance, uTagSrc, u8Level));
309 return uTagSrc;
310}
311
312
313/** @interface_method_impl{PDMAPICHLPR3,pfnSetFeatureLevel} */
314static DECLCALLBACK(void) pdmR3ApicHlp_SetFeatureLevel(PPDMDEVINS pDevIns, PDMAPICMODE enmMode)
315{
316 PDMDEV_ASSERT_DEVINS(pDevIns);
317 LogFlow(("pdmR3ApicHlp_SetFeatureLevel: caller='%s'/%d: mode=%d\n",
318 pDevIns->pReg->szName, pDevIns->iInstance, (int)enmMode));
319 switch (enmMode)
320 {
321 case PDMAPICMODE_NONE:
322 CPUMR3ClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_X2APIC);
323 CPUMR3ClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_APIC);
324 break;
325 case PDMAPICMODE_APIC:
326 CPUMR3ClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_X2APIC);
327 CPUMR3SetGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_APIC);
328 break;
329 case PDMAPICMODE_X2APIC:
330 CPUMR3SetGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_APIC);
331 CPUMR3SetGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_X2APIC);
332 break;
333 default:
334 AssertMsgFailed(("Unknown APIC mode: %d\n", (int)enmMode));
335 }
336}
337
338/** @interface_method_impl{PDMAPICHLPR3,pfnGetCpuId} */
339static DECLCALLBACK(VMCPUID) pdmR3ApicHlp_GetCpuId(PPDMDEVINS pDevIns)
340{
341 PDMDEV_ASSERT_DEVINS(pDevIns);
342 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
343 return VMMGetCpuId(pDevIns->Internal.s.pVMR3);
344}
345
346
347/** @interface_method_impl{PDMAPICHLPR3,pfnSendStartupIpi} */
348static DECLCALLBACK(void) pdmR3ApicHlp_SendStartupIpi(PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t uVector)
349{
350 PDMDEV_ASSERT_DEVINS(pDevIns);
351 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
352 VMMR3SendStartupIpi(pDevIns->Internal.s.pVMR3, idCpu, uVector);
353}
354
355
356/** @interface_method_impl{PDMAPICHLPR3,pfnSendInitIpi} */
357static DECLCALLBACK(void) pdmR3ApicHlp_SendInitIpi(PPDMDEVINS pDevIns, VMCPUID idCpu)
358{
359 PDMDEV_ASSERT_DEVINS(pDevIns);
360 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
361 VMMR3SendInitIpi(pDevIns->Internal.s.pVMR3, idCpu);
362}
363
364
365/** @interface_method_impl{PDMAPICHLPR3,pfnGetRCHelpers} */
366static DECLCALLBACK(PCPDMAPICHLPRC) pdmR3ApicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
367{
368 PDMDEV_ASSERT_DEVINS(pDevIns);
369 PVM pVM = pDevIns->Internal.s.pVMR3;
370 VM_ASSERT_EMT(pVM);
371
372 RTRCPTR pRCHelpers = NIL_RTRCPTR;
373 if (!HMIsEnabled(pVM))
374 {
375 int rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_pdmRCApicHlp", &pRCHelpers);
376 AssertReleaseRC(rc);
377 AssertRelease(pRCHelpers);
378 }
379
380 LogFlow(("pdmR3ApicHlp_GetRCHelpers: caller='%s'/%d: returns %RRv\n",
381 pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
382 return pRCHelpers;
383}
384
385
386/** @interface_method_impl{PDMAPICHLPR3,pfnGetR0Helpers} */
387static DECLCALLBACK(PCPDMAPICHLPR0) pdmR3ApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
388{
389 PDMDEV_ASSERT_DEVINS(pDevIns);
390 PVM pVM = pDevIns->Internal.s.pVMR3;
391 VM_ASSERT_EMT(pVM);
392 PCPDMAPICHLPR0 pR0Helpers = 0;
393 int rc = PDMR3LdrGetSymbolR0(pVM, NULL, "g_pdmR0ApicHlp", &pR0Helpers);
394 AssertReleaseRC(rc);
395 AssertRelease(pR0Helpers);
396 LogFlow(("pdmR3ApicHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
397 pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
398 return pR0Helpers;
399}
400
401
402/** @interface_method_impl{PDMAPICHLPR3,pfnGetR3CritSect} */
403static DECLCALLBACK(R3PTRTYPE(PPDMCRITSECT)) pdmR3ApicHlp_GetR3CritSect(PPDMDEVINS pDevIns)
404{
405 PDMDEV_ASSERT_DEVINS(pDevIns);
406 LogFlow(("pdmR3ApicHlp_Lock: caller='%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
407 return &pDevIns->Internal.s.pVMR3->pdm.s.CritSect;
408}
409
410
411/** @interface_method_impl{PDMAPICHLPR3,pfnGetRCCritSect} */
412static DECLCALLBACK(RCPTRTYPE(PPDMCRITSECT)) pdmR3ApicHlp_GetRCCritSect(PPDMDEVINS pDevIns)
413{
414 PDMDEV_ASSERT_DEVINS(pDevIns);
415 PVM pVM = pDevIns->Internal.s.pVMR3;
416 RTRCPTR RCPtr = MMHyperCCToRC(pVM, &pVM->pdm.s.CritSect);
417 LogFlow(("pdmR3ApicHlp_GetR0CritSect: caller='%s'/%d: return %RRv\n", pDevIns->pReg->szName, pDevIns->iInstance, RCPtr));
418 return RCPtr;
419}
420
421
422/** @interface_method_impl{PDMAPICHLPR3,pfnGetR3CritSect} */
423static DECLCALLBACK(R0PTRTYPE(PPDMCRITSECT)) pdmR3ApicHlp_GetR0CritSect(PPDMDEVINS pDevIns)
424{
425 PDMDEV_ASSERT_DEVINS(pDevIns);
426 PVM pVM = pDevIns->Internal.s.pVMR3;
427 RTR0PTR R0Ptr = MMHyperCCToR0(pVM, &pVM->pdm.s.CritSect);
428 LogFlow(("pdmR3ApicHlp_GetR0CritSect: caller='%s'/%d: return %RHv\n", pDevIns->pReg->szName, pDevIns->iInstance, R0Ptr));
429 return R0Ptr;
430}
431
432
433
434/**
435 * APIC Device Helpers.
436 */
437const PDMAPICHLPR3 g_pdmR3DevApicHlp =
438{
439 PDM_APICHLPR3_VERSION,
440 pdmR3ApicHlp_SetInterruptFF,
441 pdmR3ApicHlp_ClearInterruptFF,
442 pdmR3ApicHlp_BusBroadcastEoi,
443 pdmR3ApicHlp_CalcIrqTag,
444 pdmR3ApicHlp_SetFeatureLevel,
445 pdmR3ApicHlp_GetCpuId,
446 pdmR3ApicHlp_SendStartupIpi,
447 pdmR3ApicHlp_SendInitIpi,
448 pdmR3ApicHlp_GetRCHelpers,
449 pdmR3ApicHlp_GetR0Helpers,
450 pdmR3ApicHlp_GetR3CritSect,
451 pdmR3ApicHlp_GetRCCritSect,
452 pdmR3ApicHlp_GetR0CritSect,
453 PDM_APICHLPR3_VERSION /* the end */
454};
455
456/** @} */
457
458
459
460
461/** @name Ring-3 I/O APIC Helpers
462 * @{
463 */
464
465/** @interface_method_impl{PDMIOAPICHLPR3,pfnApicBusDeliver} */
466static DECLCALLBACK(int) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
467 uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc)
468{
469 PDMDEV_ASSERT_DEVINS(pDevIns);
470 PVM pVM = pDevIns->Internal.s.pVMR3;
471 LogFlow(("pdmR3IoApicHlp_ApicBusDeliver: caller='%s'/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8 uTagSrc=%#x\n",
472 pDevIns->pReg->szName, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode, uTagSrc));
473 if (pVM->pdm.s.Apic.pfnBusDeliverR3)
474 return pVM->pdm.s.Apic.pfnBusDeliverR3(pVM->pdm.s.Apic.pDevInsR3, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode, uTagSrc);
475 return VINF_SUCCESS;
476}
477
478
479/** @interface_method_impl{PDMIOAPICHLPR3,pfnLock} */
480static DECLCALLBACK(int) pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
481{
482 PDMDEV_ASSERT_DEVINS(pDevIns);
483 LogFlow(("pdmR3IoApicHlp_Lock: caller='%s'/%d: rc=%Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
484#ifdef VBOX_WITH_NEW_IOAPIC
485 AssertFailed();
486#endif
487 return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
488}
489
490
491/** @interface_method_impl{PDMIOAPICHLPR3,pfnUnlock} */
492static DECLCALLBACK(void) pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns)
493{
494 PDMDEV_ASSERT_DEVINS(pDevIns);
495 LogFlow(("pdmR3IoApicHlp_Unlock: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
496#ifdef VBOX_WITH_NEW_IOAPIC
497 AssertFailed();
498#endif
499 pdmUnlock(pDevIns->Internal.s.pVMR3);
500}
501
502
503/** @interface_method_impl{PDMIOAPICHLPR3,pfnGetRCHelpers} */
504static DECLCALLBACK(PCPDMIOAPICHLPRC) pdmR3IoApicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
505{
506 PDMDEV_ASSERT_DEVINS(pDevIns);
507 PVM pVM = pDevIns->Internal.s.pVMR3;
508 VM_ASSERT_EMT(pVM);
509
510 RTRCPTR pRCHelpers = NIL_RTRCPTR;
511 if (!HMIsEnabled(pVM))
512 {
513 int rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_pdmRCIoApicHlp", &pRCHelpers);
514 AssertReleaseRC(rc);
515 AssertRelease(pRCHelpers);
516 }
517
518 LogFlow(("pdmR3IoApicHlp_GetRCHelpers: caller='%s'/%d: returns %RRv\n",
519 pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
520 return pRCHelpers;
521}
522
523
524/** @interface_method_impl{PDMIOAPICHLPR3,pfnGetR0Helpers} */
525static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
526{
527 PDMDEV_ASSERT_DEVINS(pDevIns);
528 PVM pVM = pDevIns->Internal.s.pVMR3;
529 VM_ASSERT_EMT(pVM);
530 PCPDMIOAPICHLPR0 pR0Helpers = 0;
531 int rc = PDMR3LdrGetSymbolR0(pVM, NULL, "g_pdmR0IoApicHlp", &pR0Helpers);
532 AssertReleaseRC(rc);
533 AssertRelease(pR0Helpers);
534 LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
535 pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
536 return pR0Helpers;
537}
538
539
540/**
541 * I/O APIC Device Helpers.
542 */
543const PDMIOAPICHLPR3 g_pdmR3DevIoApicHlp =
544{
545 PDM_IOAPICHLPR3_VERSION,
546 pdmR3IoApicHlp_ApicBusDeliver,
547 pdmR3IoApicHlp_Lock,
548 pdmR3IoApicHlp_Unlock,
549 pdmR3IoApicHlp_GetRCHelpers,
550 pdmR3IoApicHlp_GetR0Helpers,
551 PDM_IOAPICHLPR3_VERSION /* the end */
552};
553
554/** @} */
555
556
557
558
559/** @name Ring-3 PCI Bus Helpers
560 * @{
561 */
562
563/** @interface_method_impl{PDMPCIHLPR3,pfnIsaSetIrq} */
564static DECLCALLBACK(void) pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
565{
566 PDMDEV_ASSERT_DEVINS(pDevIns);
567 Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
568 PVM pVM = pDevIns->Internal.s.pVMR3;
569 PDMIsaSetIrq(pDevIns->Internal.s.pVMR3, iIrq, iLevel, uTagSrc);
570}
571
572/** @interface_method_impl{PDMPCIHLPR3,pfnIoApicSetIrq} */
573static DECLCALLBACK(void) pdmR3PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
574{
575 PDMDEV_ASSERT_DEVINS(pDevIns);
576 Log4(("pdmR3PciHlp_IoApicSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
577 PDMIoApicSetIrq(pDevIns->Internal.s.pVMR3, iIrq, iLevel, uTagSrc);
578}
579
580/** @interface_method_impl{PDMPCIHLPR3,pfnIoApicSendMsi} */
581static DECLCALLBACK(void) pdmR3PciHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc)
582{
583 PDMDEV_ASSERT_DEVINS(pDevIns);
584 Log4(("pdmR3PciHlp_IoApicSendMsi: address=%p value=%x uTagSrc=%#x\n", GCPhys, uValue, uTagSrc));
585 PDMIoApicSendMsi(pDevIns->Internal.s.pVMR3, GCPhys, uValue, uTagSrc);
586}
587
588/** @interface_method_impl{PDMPCIHLPR3,pfnIsMMIO2Base} */
589static DECLCALLBACK(bool) pdmR3PciHlp_IsMMIO2Base(PPDMDEVINS pDevIns, PPDMDEVINS pOwner, RTGCPHYS GCPhys)
590{
591 PDMDEV_ASSERT_DEVINS(pDevIns);
592 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
593 bool fRc = PGMR3PhysMMIO2IsBase(pDevIns->Internal.s.pVMR3, pOwner, GCPhys);
594 Log4(("pdmR3PciHlp_IsMMIO2Base: pOwner=%p GCPhys=%RGp -> %RTbool\n", pOwner, GCPhys, fRc));
595 return fRc;
596}
597
598
599/** @interface_method_impl{PDMPCIHLPR3,pfnLock} */
600static DECLCALLBACK(int) pdmR3PciHlp_Lock(PPDMDEVINS pDevIns, int rc)
601{
602 PDMDEV_ASSERT_DEVINS(pDevIns);
603 LogFlow(("pdmR3PciHlp_Lock: caller='%s'/%d: rc=%Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
604 return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
605}
606
607
608/** @interface_method_impl{PDMPCIHLPR3,pfnUnlock} */
609static DECLCALLBACK(void) pdmR3PciHlp_Unlock(PPDMDEVINS pDevIns)
610{
611 PDMDEV_ASSERT_DEVINS(pDevIns);
612 LogFlow(("pdmR3PciHlp_Unlock: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
613 pdmUnlock(pDevIns->Internal.s.pVMR3);
614}
615
616
617/** @interface_method_impl{PDMPCIHLPR3,pfnGetRCHelpers} */
618static DECLCALLBACK(PCPDMPCIHLPRC) pdmR3PciHlp_GetRCHelpers(PPDMDEVINS pDevIns)
619{
620 PDMDEV_ASSERT_DEVINS(pDevIns);
621 PVM pVM = pDevIns->Internal.s.pVMR3;
622 VM_ASSERT_EMT(pVM);
623
624 RTRCPTR pRCHelpers = NIL_RTRCPTR;
625 if (!HMIsEnabled(pVM))
626 {
627 int rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_pdmRCPciHlp", &pRCHelpers);
628 AssertReleaseRC(rc);
629 AssertRelease(pRCHelpers);
630 }
631
632 LogFlow(("pdmR3PciHlp_GetRCHelpers: caller='%s'/%d: returns %RRv\n",
633 pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
634 return pRCHelpers;
635}
636
637
638/** @interface_method_impl{PDMPCIHLPR3,pfnGetR0Helpers} */
639static DECLCALLBACK(PCPDMPCIHLPR0) pdmR3PciHlp_GetR0Helpers(PPDMDEVINS pDevIns)
640{
641 PDMDEV_ASSERT_DEVINS(pDevIns);
642 PVM pVM = pDevIns->Internal.s.pVMR3;
643 VM_ASSERT_EMT(pVM);
644 PCPDMPCIHLPR0 pR0Helpers = 0;
645 int rc = PDMR3LdrGetSymbolR0(pVM, NULL, "g_pdmR0PciHlp", &pR0Helpers);
646 AssertReleaseRC(rc);
647 AssertRelease(pR0Helpers);
648 LogFlow(("pdmR3PciHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
649 pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
650 return pR0Helpers;
651}
652
653
654/**
655 * PCI Bus Device Helpers.
656 */
657const PDMPCIHLPR3 g_pdmR3DevPciHlp =
658{
659 PDM_PCIHLPR3_VERSION,
660 pdmR3PciHlp_IsaSetIrq,
661 pdmR3PciHlp_IoApicSetIrq,
662 pdmR3PciHlp_IoApicSendMsi,
663 pdmR3PciHlp_IsMMIO2Base,
664 pdmR3PciHlp_GetRCHelpers,
665 pdmR3PciHlp_GetR0Helpers,
666 pdmR3PciHlp_Lock,
667 pdmR3PciHlp_Unlock,
668 PDM_PCIHLPR3_VERSION, /* the end */
669};
670
671/** @} */
672
673
674
675
676/** @name Ring-3 HPET Helpers
677 * {@
678 */
679
680/** @interface_method_impl{PDMHPETHLPR3,pfnSetLegacyMode} */
681static DECLCALLBACK(int) pdmR3HpetHlp_SetLegacyMode(PPDMDEVINS pDevIns, bool fActivated)
682{
683 PDMDEV_ASSERT_DEVINS(pDevIns);
684 LogFlow(("pdmR3HpetHlp_SetLegacyMode: caller='%s'/%d: fActivated=%RTbool\n", pDevIns->pReg->szName, pDevIns->iInstance, fActivated));
685
686 size_t i;
687 int rc = VINF_SUCCESS;
688 static const char * const s_apszDevsToNotify[] =
689 {
690 "i8254",
691 "mc146818"
692 };
693 for (i = 0; i < RT_ELEMENTS(s_apszDevsToNotify); i++)
694 {
695 PPDMIBASE pBase;
696 rc = PDMR3QueryDevice(pDevIns->Internal.s.pVMR3->pUVM, "i8254", 0, &pBase);
697 if (RT_SUCCESS(rc))
698 {
699 PPDMIHPETLEGACYNOTIFY pPort = PDMIBASE_QUERY_INTERFACE(pBase, PDMIHPETLEGACYNOTIFY);
700 AssertLogRelMsgBreakStmt(pPort, ("%s\n", s_apszDevsToNotify[i]), rc = VERR_PDM_HPET_LEGACY_NOTIFY_MISSING);
701 pPort->pfnModeChanged(pPort, fActivated);
702 }
703 else if ( rc == VERR_PDM_DEVICE_NOT_FOUND
704 || rc == VERR_PDM_DEVICE_INSTANCE_NOT_FOUND)
705 rc = VINF_SUCCESS; /* the device isn't configured, ignore. */
706 else
707 AssertLogRelMsgFailedBreak(("%s -> %Rrc\n", s_apszDevsToNotify[i], rc));
708 }
709
710 /* Don't bother cleaning up, any failure here will cause a guru meditation. */
711
712 LogFlow(("pdmR3HpetHlp_SetLegacyMode: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
713 return rc;
714}
715
716
717/** @interface_method_impl{PDMHPETHLPR3,pfnSetIrq} */
718static DECLCALLBACK(int) pdmR3HpetHlp_SetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
719{
720 PDMDEV_ASSERT_DEVINS(pDevIns);
721 LogFlow(("pdmR3HpetHlp_SetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
722 PVM pVM = pDevIns->Internal.s.pVMR3;
723
724 pdmLock(pVM);
725 uint32_t uTagSrc;
726 if (iLevel & PDM_IRQ_LEVEL_HIGH)
727 {
728 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
729 if (iLevel == PDM_IRQ_LEVEL_HIGH)
730 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
731 else
732 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
733 }
734 else
735 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
736
737 PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */
738
739 if (iLevel == PDM_IRQ_LEVEL_LOW)
740 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
741 pdmUnlock(pVM);
742 return 0;
743}
744
745
746/** @interface_method_impl{PDMHPETHLPR3,pfnGetRCHelpers} */
747static DECLCALLBACK(PCPDMHPETHLPRC) pdmR3HpetHlp_GetRCHelpers(PPDMDEVINS pDevIns)
748{
749 PDMDEV_ASSERT_DEVINS(pDevIns);
750 PVM pVM = pDevIns->Internal.s.pVMR3;
751 VM_ASSERT_EMT(pVM);
752
753 RTRCPTR pRCHelpers = NIL_RTRCPTR;
754 if (!HMIsEnabled(pVM))
755 {
756 int rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_pdmRCHpetHlp", &pRCHelpers);
757 AssertReleaseRC(rc);
758 AssertRelease(pRCHelpers);
759 }
760
761 LogFlow(("pdmR3HpetHlp_GetGCHelpers: caller='%s'/%d: returns %RRv\n",
762 pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
763 return pRCHelpers;
764}
765
766
767/** @interface_method_impl{PDMHPETHLPR3,pfnGetR0Helpers} */
768static DECLCALLBACK(PCPDMHPETHLPR0) pdmR3HpetHlp_GetR0Helpers(PPDMDEVINS pDevIns)
769{
770 PDMDEV_ASSERT_DEVINS(pDevIns);
771 PVM pVM = pDevIns->Internal.s.pVMR3;
772 VM_ASSERT_EMT(pVM);
773 PCPDMHPETHLPR0 pR0Helpers = 0;
774 int rc = PDMR3LdrGetSymbolR0(pVM, NULL, "g_pdmR0HpetHlp", &pR0Helpers);
775 AssertReleaseRC(rc);
776 AssertRelease(pR0Helpers);
777 LogFlow(("pdmR3HpetHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
778 pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
779 return pR0Helpers;
780}
781
782
783/**
784 * HPET Device Helpers.
785 */
786const PDMHPETHLPR3 g_pdmR3DevHpetHlp =
787{
788 PDM_HPETHLPR3_VERSION,
789 pdmR3HpetHlp_GetRCHelpers,
790 pdmR3HpetHlp_GetR0Helpers,
791 pdmR3HpetHlp_SetLegacyMode,
792 pdmR3HpetHlp_SetIrq,
793 PDM_HPETHLPR3_VERSION, /* the end */
794};
795
796/** @} */
797
798
799/** @name Ring-3 Raw PCI Device Helpers
800 * {@
801 */
802
803/** @interface_method_impl{PDMPCIRAWHLPR3,pfnGetRCHelpers} */
804static DECLCALLBACK(PCPDMPCIRAWHLPRC) pdmR3PciRawHlp_GetRCHelpers(PPDMDEVINS pDevIns)
805{
806 PDMDEV_ASSERT_DEVINS(pDevIns);
807 PVM pVM = pDevIns->Internal.s.pVMR3;
808 VM_ASSERT_EMT(pVM);
809
810 RTRCPTR pRCHelpers = NIL_RTRCPTR;
811 if (!HMIsEnabled(pVM))
812 {
813 int rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_pdmRCPciRawHlp", &pRCHelpers);
814 AssertReleaseRC(rc);
815 AssertRelease(pRCHelpers);
816 }
817
818 LogFlow(("pdmR3PciRawHlp_GetGCHelpers: caller='%s'/%d: returns %RRv\n",
819 pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
820 return pRCHelpers;
821}
822
823
824/** @interface_method_impl{PDMPCIRAWHLPR3,pfnGetR0Helpers} */
825static DECLCALLBACK(PCPDMPCIRAWHLPR0) pdmR3PciRawHlp_GetR0Helpers(PPDMDEVINS pDevIns)
826{
827 PDMDEV_ASSERT_DEVINS(pDevIns);
828 PVM pVM = pDevIns->Internal.s.pVMR3;
829 VM_ASSERT_EMT(pVM);
830 PCPDMHPETHLPR0 pR0Helpers = NIL_RTR0PTR;
831 int rc = PDMR3LdrGetSymbolR0(pVM, NULL, "g_pdmR0PciRawHlp", &pR0Helpers);
832 AssertReleaseRC(rc);
833 AssertRelease(pR0Helpers);
834 LogFlow(("pdmR3PciRawHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
835 pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
836 return pR0Helpers;
837}
838
839
840/**
841 * Raw PCI Device Helpers.
842 */
843const PDMPCIRAWHLPR3 g_pdmR3DevPciRawHlp =
844{
845 PDM_PCIRAWHLPR3_VERSION,
846 pdmR3PciRawHlp_GetRCHelpers,
847 pdmR3PciRawHlp_GetR0Helpers,
848 PDM_PCIRAWHLPR3_VERSION, /* the end */
849};
850
851/** @} */
852
853
854/* none yet */
855
856/**
857 * Firmware Device Helpers.
858 */
859const PDMFWHLPR3 g_pdmR3DevFirmwareHlp =
860{
861 PDM_FWHLPR3_VERSION,
862 PDM_FWHLPR3_VERSION
863};
864
865/**
866 * DMAC Device Helpers.
867 */
868const PDMDMACHLP g_pdmR3DevDmacHlp =
869{
870 PDM_DMACHLP_VERSION
871};
872
873
874
875
876/* none yet */
877
878/**
879 * RTC Device Helpers.
880 */
881const PDMRTCHLP g_pdmR3DevRtcHlp =
882{
883 PDM_RTCHLP_VERSION
884};
885
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