VirtualBox

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

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

VMM: APIC rewrite. Initial commit, work in progress.

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