VirtualBox

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

Last change on this file since 86204 was 86070, checked in by vboxsync, 4 years ago

AMD IOMMU: bugref:9654 Fix accidentally not copying/initialize MSIMSG values. Fix using the translated memory address on
successful translations from the IOMMU. Fix not remapping any interrupt when IOMMU code is compiled but an IOMMU is not present.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 13.7 KB
Line 
1/* $Id: PDMDevMiscHlp.cpp 86070 2020-09-09 09:50:01Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, Misc. Device Helpers.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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#include <VBox/vmm/apic.h>
28#include <VBox/vmm/vm.h>
29#include <VBox/vmm/vmm.h>
30
31#include <VBox/log.h>
32#include <VBox/err.h>
33#include <VBox/msi.h>
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/thread.h>
37
38
39#include "PDMInline.h"
40#include "dtrace/VBoxVMM.h"
41
42
43
44/** @name Ring-3 PIC Helpers
45 * @{
46 */
47
48/** @interface_method_impl{PDMPICHLP,pfnSetInterruptFF} */
49static DECLCALLBACK(void) pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
50{
51 PDMDEV_ASSERT_DEVINS(pDevIns);
52 PVM pVM = pDevIns->Internal.s.pVMR3;
53 PVMCPU pVCpu = pVM->apCpusR3[0]; /* for PIC we always deliver to CPU 0, SMP uses APIC */
54
55 /* IRQ state should be loaded as-is by "LoadExec". Changes can be made from LoadDone. */
56 Assert(pVM->enmVMState != VMSTATE_LOADING || pVM->pdm.s.fStateLoaded);
57
58 APICLocalInterrupt(pVCpu, 0 /* u8Pin */, 1 /* u8Level */, VINF_SUCCESS /* rcRZ */);
59}
60
61
62/** @interface_method_impl{PDMPICHLP,pfnClearInterruptFF} */
63static DECLCALLBACK(void) pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
64{
65 PDMDEV_ASSERT_DEVINS(pDevIns);
66 PVM pVM = pDevIns->Internal.s.pVMR3;
67 PVMCPU pVCpu = pVM->apCpusR3[0]; /* for PIC we always deliver to CPU 0, SMP uses APIC */
68
69 /* IRQ state should be loaded as-is by "LoadExec". Changes can be made from LoadDone. */
70 Assert(pVM->enmVMState != VMSTATE_LOADING || pVM->pdm.s.fStateLoaded);
71
72 APICLocalInterrupt(pVCpu, 0 /* u8Pin */, 0 /* u8Level */, VINF_SUCCESS /* rcRZ */);
73}
74
75
76/** @interface_method_impl{PDMPICHLP,pfnLock} */
77static DECLCALLBACK(int) pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
78{
79 PDMDEV_ASSERT_DEVINS(pDevIns);
80 return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
81}
82
83
84/** @interface_method_impl{PDMPICHLP,pfnUnlock} */
85static DECLCALLBACK(void) pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns)
86{
87 PDMDEV_ASSERT_DEVINS(pDevIns);
88 pdmUnlock(pDevIns->Internal.s.pVMR3);
89}
90
91
92/**
93 * PIC Device Helpers.
94 */
95const PDMPICHLP g_pdmR3DevPicHlp =
96{
97 PDM_PICHLP_VERSION,
98 pdmR3PicHlp_SetInterruptFF,
99 pdmR3PicHlp_ClearInterruptFF,
100 pdmR3PicHlp_Lock,
101 pdmR3PicHlp_Unlock,
102 PDM_PICHLP_VERSION /* the end */
103};
104
105/** @} */
106
107
108/** @name Ring-3 I/O APIC Helpers
109 * @{
110 */
111
112/** @interface_method_impl{PDMIOAPICHLP,pfnApicBusDeliver} */
113static DECLCALLBACK(int) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode,
114 uint8_t u8DeliveryMode, uint8_t uVector, uint8_t u8Polarity,
115 uint8_t u8TriggerMode, uint32_t uTagSrc)
116{
117 PDMDEV_ASSERT_DEVINS(pDevIns);
118 PVM pVM = pDevIns->Internal.s.pVMR3;
119 LogFlow(("pdmR3IoApicHlp_ApicBusDeliver: caller='%s'/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 uVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8 uTagSrc=%#x\n",
120 pDevIns->pReg->szName, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, uVector, u8Polarity, u8TriggerMode, uTagSrc));
121 return APICBusDeliver(pVM, u8Dest, u8DestMode, u8DeliveryMode, uVector, u8Polarity, u8TriggerMode, uTagSrc);
122}
123
124
125/** @interface_method_impl{PDMIOAPICHLP,pfnLock} */
126static DECLCALLBACK(int) pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
127{
128 PDMDEV_ASSERT_DEVINS(pDevIns);
129 LogFlow(("pdmR3IoApicHlp_Lock: caller='%s'/%d: rc=%Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
130 return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
131}
132
133
134/** @interface_method_impl{PDMIOAPICHLP,pfnUnlock} */
135static DECLCALLBACK(void) pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns)
136{
137 PDMDEV_ASSERT_DEVINS(pDevIns);
138 LogFlow(("pdmR3IoApicHlp_Unlock: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
139 pdmUnlock(pDevIns->Internal.s.pVMR3);
140}
141
142
143/** @interface_method_impl{PDMIOAPICHLP,pfnIommuMsiRemap} */
144static DECLCALLBACK(int) pdmR3IoApicHlp_IommuMsiRemap(PPDMDEVINS pDevIns, uint16_t uDevId, PCMSIMSG pMsiIn, PMSIMSG pMsiOut)
145{
146 PDMDEV_ASSERT_DEVINS(pDevIns);
147 LogFlow(("pdmR3IoApicHlp_IommuRemapMsi: caller='%s'/%d: pMsiIn=(%#RX64, %#RU32)\n", pDevIns->pReg->szName,
148 pDevIns->iInstance, pMsiIn->Addr.u64, pMsiIn->Data.u32));
149
150#ifdef VBOX_WITH_IOMMU_AMD
151 /** @todo IOMMU: Optimize/re-organize things here later. */
152 PVM pVM = pDevIns->Internal.s.pVMR3;
153 PPDMIOMMU pIommu = &pVM->pdm.s.aIommus[0];
154 PPDMDEVINS pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
155 if ( pDevInsIommu
156 && pDevInsIommu != pDevIns)
157 {
158 int rc = pIommu->pfnMsiRemap(pDevInsIommu, uDevId, pMsiIn, pMsiOut);
159 if (RT_SUCCESS(rc))
160 return rc;
161
162 Log(("pdmR3IoApicHlp_IommuRemapMsi: IOMMU MSI remap failed. uDevId=%#x pMsiIn=(%#RX64, %#RU32) rc=%Rrc\n",
163 uDevId, pMsiIn->Addr.u64, pMsiIn->Data.u32, rc));
164 return rc;
165 }
166#else
167 RT_NOREF(pDevIns, uDevId);
168#endif
169 *pMsiOut = *pMsiIn;
170 return VINF_SUCCESS;
171}
172
173
174/**
175 * I/O APIC Device Helpers.
176 */
177const PDMIOAPICHLP g_pdmR3DevIoApicHlp =
178{
179 PDM_IOAPICHLP_VERSION,
180 pdmR3IoApicHlp_ApicBusDeliver,
181 pdmR3IoApicHlp_Lock,
182 pdmR3IoApicHlp_Unlock,
183 pdmR3IoApicHlp_IommuMsiRemap,
184 PDM_IOAPICHLP_VERSION /* the end */
185};
186
187/** @} */
188
189
190
191
192/** @name Ring-3 PCI Bus Helpers
193 * @{
194 */
195
196/** @interface_method_impl{PDMPCIHLPR3,pfnIsaSetIrq} */
197static DECLCALLBACK(void) pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
198{
199 PDMDEV_ASSERT_DEVINS(pDevIns);
200 Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc));
201 PDMIsaSetIrq(pDevIns->Internal.s.pVMR3, iIrq, iLevel, uTagSrc);
202}
203
204
205/** @interface_method_impl{PDMPCIHLPR3,pfnIoApicSetIrq} */
206static DECLCALLBACK(void) pdmR3PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, PCIBDF uBusDevFn, int iIrq, int iLevel, uint32_t uTagSrc)
207{
208 PDMDEV_ASSERT_DEVINS(pDevIns);
209 Log4(("pdmR3PciHlp_IoApicSetIrq: uBusDevFn=%#x iIrq=%d iLevel=%d uTagSrc=%#x\n", uBusDevFn, iIrq, iLevel, uTagSrc));
210 PDMIoApicSetIrq(pDevIns->Internal.s.pVMR3, uBusDevFn, iIrq, iLevel, uTagSrc);
211}
212
213
214/** @interface_method_impl{PDMPCIHLPR3,pfnIoApicSendMsi} */
215static DECLCALLBACK(void) pdmR3PciHlp_IoApicSendMsi(PPDMDEVINS pDevIns, PCIBDF uBusDevFn, PCMSIMSG pMsi, uint32_t uTagSrc)
216{
217 PDMDEV_ASSERT_DEVINS(pDevIns);
218 Assert(PCIBDF_IS_VALID(uBusDevFn));
219 Log4(("pdmR3PciHlp_IoApicSendMsi: uBusDevFn=%#x Msi (Addr=%#RX64 Data=%#x) uTagSrc=%#x\n", uBusDevFn,
220 pMsi->Addr.u64, pMsi->Data.u32, uTagSrc));
221 PDMIoApicSendMsi(pDevIns->Internal.s.pVMR3, uBusDevFn, pMsi, uTagSrc);
222}
223
224
225/** @interface_method_impl{PDMPCIHLPR3,pfnLock} */
226static DECLCALLBACK(int) pdmR3PciHlp_Lock(PPDMDEVINS pDevIns, int rc)
227{
228 PDMDEV_ASSERT_DEVINS(pDevIns);
229 LogFlow(("pdmR3PciHlp_Lock: caller='%s'/%d: rc=%Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
230 return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
231}
232
233
234/** @interface_method_impl{PDMPCIHLPR3,pfnUnlock} */
235static DECLCALLBACK(void) pdmR3PciHlp_Unlock(PPDMDEVINS pDevIns)
236{
237 PDMDEV_ASSERT_DEVINS(pDevIns);
238 LogFlow(("pdmR3PciHlp_Unlock: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
239 pdmUnlock(pDevIns->Internal.s.pVMR3);
240}
241
242
243/** @interface_method_impl{PDMPCIHLPR3,pfnGetBusByNo} */
244static DECLCALLBACK(PPDMDEVINS) pdmR3PciHlp_GetBusByNo(PPDMDEVINS pDevIns, uint32_t idxPdmBus)
245{
246 PDMDEV_ASSERT_DEVINS(pDevIns);
247 PVM pVM = pDevIns->Internal.s.pVMR3;
248 AssertReturn(idxPdmBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), NULL);
249 PPDMDEVINS pRetDevIns = pVM->pdm.s.aPciBuses[idxPdmBus].pDevInsR3;
250 LogFlow(("pdmR3PciHlp_GetBusByNo: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pRetDevIns));
251 return pRetDevIns;
252}
253
254
255/**
256 * PCI Bus Device Helpers.
257 */
258const PDMPCIHLPR3 g_pdmR3DevPciHlp =
259{
260 PDM_PCIHLPR3_VERSION,
261 pdmR3PciHlp_IsaSetIrq,
262 pdmR3PciHlp_IoApicSetIrq,
263 pdmR3PciHlp_IoApicSendMsi,
264 pdmR3PciHlp_Lock,
265 pdmR3PciHlp_Unlock,
266 pdmR3PciHlp_GetBusByNo,
267 PDM_PCIHLPR3_VERSION, /* the end */
268};
269
270/** @} */
271
272
273/**
274 * IOMMU Device Helpers.
275 */
276const PDMIOMMUHLPR3 g_pdmR3DevIommuHlp =
277{
278 PDM_IOMMUHLPR3_VERSION,
279 PDM_IOMMUHLPR3_VERSION /* the end */
280};
281
282
283/** @name Ring-3 HPET Helpers
284 * @{
285 */
286
287/** @interface_method_impl{PDMHPETHLPR3,pfnSetLegacyMode} */
288static DECLCALLBACK(int) pdmR3HpetHlp_SetLegacyMode(PPDMDEVINS pDevIns, bool fActivated)
289{
290 PDMDEV_ASSERT_DEVINS(pDevIns);
291 LogFlow(("pdmR3HpetHlp_SetLegacyMode: caller='%s'/%d: fActivated=%RTbool\n", pDevIns->pReg->szName, pDevIns->iInstance, fActivated));
292
293 size_t i;
294 int rc = VINF_SUCCESS;
295 static const char * const s_apszDevsToNotify[] =
296 {
297 "i8254",
298 "mc146818"
299 };
300 for (i = 0; i < RT_ELEMENTS(s_apszDevsToNotify); i++)
301 {
302 PPDMIBASE pBase;
303 rc = PDMR3QueryDevice(pDevIns->Internal.s.pVMR3->pUVM, "i8254", 0, &pBase);
304 if (RT_SUCCESS(rc))
305 {
306 PPDMIHPETLEGACYNOTIFY pPort = PDMIBASE_QUERY_INTERFACE(pBase, PDMIHPETLEGACYNOTIFY);
307 AssertLogRelMsgBreakStmt(pPort, ("%s\n", s_apszDevsToNotify[i]), rc = VERR_PDM_HPET_LEGACY_NOTIFY_MISSING);
308 pPort->pfnModeChanged(pPort, fActivated);
309 }
310 else if ( rc == VERR_PDM_DEVICE_NOT_FOUND
311 || rc == VERR_PDM_DEVICE_INSTANCE_NOT_FOUND)
312 rc = VINF_SUCCESS; /* the device isn't configured, ignore. */
313 else
314 AssertLogRelMsgFailedBreak(("%s -> %Rrc\n", s_apszDevsToNotify[i], rc));
315 }
316
317 /* Don't bother cleaning up, any failure here will cause a guru meditation. */
318
319 LogFlow(("pdmR3HpetHlp_SetLegacyMode: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
320 return rc;
321}
322
323
324/** @interface_method_impl{PDMHPETHLPR3,pfnSetIrq} */
325static DECLCALLBACK(int) pdmR3HpetHlp_SetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
326{
327 PDMDEV_ASSERT_DEVINS(pDevIns);
328 LogFlow(("pdmR3HpetHlp_SetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
329 PVM pVM = pDevIns->Internal.s.pVMR3;
330
331 pdmLock(pVM);
332 uint32_t uTagSrc;
333 if (iLevel & PDM_IRQ_LEVEL_HIGH)
334 {
335 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
336 if (iLevel == PDM_IRQ_LEVEL_HIGH)
337 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
338 else
339 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
340 }
341 else
342 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
343
344 PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */
345
346 if (iLevel == PDM_IRQ_LEVEL_LOW)
347 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
348 pdmUnlock(pVM);
349 return 0;
350}
351
352
353/**
354 * HPET Device Helpers.
355 */
356const PDMHPETHLPR3 g_pdmR3DevHpetHlp =
357{
358 PDM_HPETHLPR3_VERSION,
359 pdmR3HpetHlp_SetLegacyMode,
360 pdmR3HpetHlp_SetIrq,
361 PDM_HPETHLPR3_VERSION, /* the end */
362};
363
364/** @} */
365
366
367/** @name Ring-3 Raw PCI Device Helpers
368 * @{
369 */
370
371/** @interface_method_impl{PDMPCIRAWHLPR3,pfnGetRCHelpers} */
372static DECLCALLBACK(PCPDMPCIRAWHLPRC) pdmR3PciRawHlp_GetRCHelpers(PPDMDEVINS pDevIns)
373{
374 PDMDEV_ASSERT_DEVINS(pDevIns);
375 PVM pVM = pDevIns->Internal.s.pVMR3;
376 VM_ASSERT_EMT(pVM);
377
378 RTRCPTR pRCHelpers = NIL_RTRCPTR;
379 if (VM_IS_RAW_MODE_ENABLED(pVM))
380 {
381 int rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_pdmRCPciRawHlp", &pRCHelpers);
382 AssertReleaseRC(rc);
383 AssertRelease(pRCHelpers);
384 }
385
386 LogFlow(("pdmR3PciRawHlp_GetGCHelpers: caller='%s'/%d: returns %RRv\n",
387 pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers));
388 return pRCHelpers;
389}
390
391
392/** @interface_method_impl{PDMPCIRAWHLPR3,pfnGetR0Helpers} */
393static DECLCALLBACK(PCPDMPCIRAWHLPR0) pdmR3PciRawHlp_GetR0Helpers(PPDMDEVINS pDevIns)
394{
395 PDMDEV_ASSERT_DEVINS(pDevIns);
396 PVM pVM = pDevIns->Internal.s.pVMR3;
397 VM_ASSERT_EMT(pVM);
398 PCPDMHPETHLPR0 pR0Helpers = NIL_RTR0PTR;
399 int rc = PDMR3LdrGetSymbolR0(pVM, NULL, "g_pdmR0PciRawHlp", &pR0Helpers);
400 AssertReleaseRC(rc);
401 AssertRelease(pR0Helpers);
402 LogFlow(("pdmR3PciRawHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n",
403 pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers));
404 return pR0Helpers;
405}
406
407
408/**
409 * Raw PCI Device Helpers.
410 */
411const PDMPCIRAWHLPR3 g_pdmR3DevPciRawHlp =
412{
413 PDM_PCIRAWHLPR3_VERSION,
414 pdmR3PciRawHlp_GetRCHelpers,
415 pdmR3PciRawHlp_GetR0Helpers,
416 PDM_PCIRAWHLPR3_VERSION, /* the end */
417};
418
419/** @} */
420
421
422/* none yet */
423
424/**
425 * Firmware Device Helpers.
426 */
427const PDMFWHLPR3 g_pdmR3DevFirmwareHlp =
428{
429 PDM_FWHLPR3_VERSION,
430 PDM_FWHLPR3_VERSION
431};
432
433/**
434 * DMAC Device Helpers.
435 */
436const PDMDMACHLP g_pdmR3DevDmacHlp =
437{
438 PDM_DMACHLP_VERSION
439};
440
441
442
443
444/* none yet */
445
446/**
447 * RTC Device Helpers.
448 */
449const PDMRTCHLP g_pdmR3DevRtcHlp =
450{
451 PDM_RTCHLP_VERSION
452};
453
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