VirtualBox

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

Last change on this file since 34834 was 32935, checked in by vboxsync, 14 years ago

PDM, VMM, PCI: reworked MSI API: now MSIs delivered via IOAPIC API, not with MMIO access, LSI logic now can work in MSI mode

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