VirtualBox

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

Last change on this file since 61068 was 60804, checked in by vboxsync, 9 years ago

VMM: Introduced the new APIC update force-flag and relevant fixes, Win8.1 SMP boots now.
VMM/HMVMXR0: Fixed the HLT exit to use instruction length and also keep the INHIBIT force-flag
more in sync with the VT-x's guest-interruptibility state.

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