VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/PDMDevHlpTracing.cpp@ 86087

Last change on this file since 86087 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 Author Date Id Revision
File size: 25.2 KB
Line 
1/* $Id: PDMDevHlpTracing.cpp 86070 2020-09-09 09:50:01Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, Device Helper variants when tracing is enabled.
4 */
5
6/*
7 * Copyright (C) 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#define PDMPCIDEV_INCLUDE_PRIVATE /* Hack to get pdmpcidevint.h included at the right point. */
24#include "PDMInternal.h"
25#include <VBox/vmm/pdm.h>
26#include <VBox/vmm/mm.h>
27#include <VBox/vmm/hm.h>
28#include <VBox/vmm/pgm.h>
29#include <VBox/vmm/iom.h>
30#include <VBox/vmm/dbgf.h>
31#include <VBox/vmm/ssm.h>
32#include <VBox/vmm/vmapi.h>
33#include <VBox/vmm/vmm.h>
34#include <VBox/vmm/vmcc.h>
35
36#include <VBox/version.h>
37#include <VBox/log.h>
38#include <VBox/err.h>
39#include <iprt/asm.h>
40#include <iprt/assert.h>
41#include <iprt/ctype.h>
42#include <iprt/string.h>
43#include <iprt/thread.h>
44
45#include "dtrace/VBoxVMM.h"
46#include "PDMInline.h"
47
48
49/*********************************************************************************************************************************
50* Defined Constants And Macros *
51*********************************************************************************************************************************/
52/** @name R3 DevHlp
53 * @{
54 */
55
56
57static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlpTracing_IoPortNewIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
58{
59 PCPDMDEVINSDBGFTRACK pTrack = (PCPDMDEVINSDBGFTRACK)pvUser;
60
61 Assert(!pTrack->fMmio);
62 PVM pVM = pDevIns->Internal.s.pVMR3;
63 VBOXSTRICTRC rcStrict = pTrack->u.IoPort.pfnIn(pDevIns, pTrack->pvUser, offPort, pu32, cb);
64 if (RT_SUCCESS(rcStrict))
65 DBGFTracerEvtIoPortRead(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, pTrack->u.IoPort.hIoPorts, offPort, pu32, cb);
66
67 return rcStrict;
68}
69
70
71static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlpTracing_IoPortNewInStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint8_t *pbDst,
72 uint32_t *pcTransfers, unsigned cb)
73{
74 PCPDMDEVINSDBGFTRACK pTrack = (PCPDMDEVINSDBGFTRACK)pvUser;
75
76 Assert(!pTrack->fMmio);
77 PVM pVM = pDevIns->Internal.s.pVMR3;
78 uint32_t cTransfersReq = *pcTransfers;
79 VBOXSTRICTRC rcStrict = pTrack->u.IoPort.pfnInStr(pDevIns, pTrack->pvUser, offPort, pbDst, pcTransfers, cb);
80 if (RT_SUCCESS(rcStrict))
81 DBGFTracerEvtIoPortReadStr(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, pTrack->u.IoPort.hIoPorts, offPort, pbDst, cb,
82 cTransfersReq, cTransfersReq - *pcTransfers);
83
84 return rcStrict;
85}
86
87
88static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlpTracing_IoPortNewOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
89{
90 PCPDMDEVINSDBGFTRACK pTrack = (PCPDMDEVINSDBGFTRACK)pvUser;
91
92 Assert(!pTrack->fMmio);
93 PVM pVM = pDevIns->Internal.s.pVMR3;
94 VBOXSTRICTRC rcStrict = pTrack->u.IoPort.pfnOut(pDevIns, pTrack->pvUser, offPort, u32, cb);
95 if (RT_SUCCESS(rcStrict))
96 DBGFTracerEvtIoPortWrite(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, pTrack->u.IoPort.hIoPorts, offPort, &u32, cb);
97
98 return rcStrict;
99}
100
101
102static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlpTracing_IoPortNewOutStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, const uint8_t *pbSrc,
103 uint32_t *pcTransfers, unsigned cb)
104{
105 PCPDMDEVINSDBGFTRACK pTrack = (PCPDMDEVINSDBGFTRACK)pvUser;
106
107 Assert(!pTrack->fMmio);
108 PVM pVM = pDevIns->Internal.s.pVMR3;
109 uint32_t cTransfersReq = *pcTransfers;
110 VBOXSTRICTRC rcStrict = pTrack->u.IoPort.pfnOutStr(pDevIns, pTrack->pvUser, offPort, pbSrc, pcTransfers, cb);
111 if (RT_SUCCESS(rcStrict))
112 DBGFTracerEvtIoPortWriteStr(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, pTrack->u.IoPort.hIoPorts, offPort, pbSrc, cb,
113 cTransfersReq, cTransfersReq - *pcTransfers);
114
115 return rcStrict;
116}
117
118
119static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlpTracing_MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, uint32_t cb)
120{
121 PCPDMDEVINSDBGFTRACK pTrack = (PCPDMDEVINSDBGFTRACK)pvUser;
122
123 Assert(pTrack->fMmio);
124 PVM pVM = pDevIns->Internal.s.pVMR3;
125 VBOXSTRICTRC rcStrict = pTrack->u.Mmio.pfnRead(pDevIns, pTrack->pvUser, off, pv, cb);
126 if (RT_SUCCESS(rcStrict))
127 DBGFTracerEvtMmioRead(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, pTrack->u.Mmio.hMmioRegion, off, pv, cb);
128
129 return rcStrict;
130}
131
132
133static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlpTracing_MmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, uint32_t cb)
134{
135 PCPDMDEVINSDBGFTRACK pTrack = (PCPDMDEVINSDBGFTRACK)pvUser;
136
137 Assert(pTrack->fMmio);
138 PVM pVM = pDevIns->Internal.s.pVMR3;
139 VBOXSTRICTRC rcStrict = pTrack->u.Mmio.pfnWrite(pDevIns, pTrack->pvUser, off, pv, cb);
140 if (RT_SUCCESS(rcStrict))
141 DBGFTracerEvtMmioWrite(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, pTrack->u.Mmio.hMmioRegion, off, pv, cb);
142
143 return rcStrict;
144}
145
146
147static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlpTracing_MmioFill(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off,
148 uint32_t u32Item, uint32_t cbItem, uint32_t cItems)
149{
150 PCPDMDEVINSDBGFTRACK pTrack = (PCPDMDEVINSDBGFTRACK)pvUser;
151
152 Assert(pTrack->fMmio);
153 PVM pVM = pDevIns->Internal.s.pVMR3;
154 VBOXSTRICTRC rcStrict = pTrack->u.Mmio.pfnFill(pDevIns, pTrack->pvUser, off, u32Item, cbItem, cItems);
155 if (RT_SUCCESS(rcStrict))
156 DBGFTracerEvtMmioFill(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, pTrack->u.Mmio.hMmioRegion, off,
157 u32Item, cbItem, cItems);
158
159 return rcStrict;
160}
161
162
163/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortCreateEx} */
164DECL_HIDDEN_CALLBACK(int)
165pdmR3DevHlpTracing_IoPortCreateEx(PPDMDEVINS pDevIns, RTIOPORT cPorts, uint32_t fFlags, PPDMPCIDEV pPciDev,
166 uint32_t iPciRegion, PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
167 PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr, RTR3PTR pvUser,
168 const char *pszDesc, PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts)
169{
170 PDMDEV_ASSERT_DEVINS(pDevIns);
171 LogFlow(("pdmR3DevHlpTracing_IoPortCreateEx: caller='%s'/%d: cPorts=%#x fFlags=%#x pPciDev=%p iPciRegion=%#x pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pvUser=%p pszDesc=%p:{%s} paExtDescs=%p phIoPorts=%p\n",
172 pDevIns->pReg->szName, pDevIns->iInstance, cPorts, fFlags, pPciDev, iPciRegion, pfnOut, pfnIn, pfnOutStr, pfnInStr,
173 pvUser, pszDesc, pszDesc, paExtDescs, phIoPorts));
174 PVM pVM = pDevIns->Internal.s.pVMR3;
175 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
176 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
177
178 int rc = VINF_SUCCESS;
179 if (pDevIns->Internal.s.idxDbgfTraceTrackNext < pDevIns->Internal.s.cDbgfTraceTrackMax)
180 {
181 PPDMDEVINSDBGFTRACK pTrack = &pDevIns->Internal.s.paDbgfTraceTrack[pDevIns->Internal.s.idxDbgfTraceTrackNext];
182
183 rc = IOMR3IoPortCreate(pVM, pDevIns, cPorts, fFlags, pPciDev, iPciRegion,
184 pfnOut ? pdmR3DevHlpTracing_IoPortNewOut : NULL,
185 pfnIn ? pdmR3DevHlpTracing_IoPortNewIn : NULL,
186 pfnOutStr ? pdmR3DevHlpTracing_IoPortNewOutStr : NULL,
187 pfnInStr ? pdmR3DevHlpTracing_IoPortNewInStr : NULL,
188 pTrack, pszDesc, paExtDescs, phIoPorts);
189 if (RT_SUCCESS(rc))
190 {
191 pTrack->fMmio = false;
192 pTrack->pvUser = pvUser;
193 pTrack->u.IoPort.hIoPorts = *phIoPorts;
194 pTrack->u.IoPort.pfnOut = pfnOut;
195 pTrack->u.IoPort.pfnIn = pfnIn;
196 pTrack->u.IoPort.pfnOutStr = pfnOutStr;
197 pTrack->u.IoPort.pfnInStr = pfnInStr;
198 pDevIns->Internal.s.idxDbgfTraceTrackNext++;
199 DBGFR3TracerEvtIoPortCreate(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, *phIoPorts, cPorts, fFlags, iPciRegion);
200 }
201 }
202 else
203 rc = VERR_OUT_OF_RESOURCES;
204
205 LogFlow(("pdmR3DevHlpTracing_IoPortCreateEx: caller='%s'/%d: returns %Rrc (*phIoPorts=%#x)\n",
206 pDevIns->pReg->szName, pDevIns->iInstance, rc, *phIoPorts));
207 return rc;
208}
209
210
211/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortMap} */
212DECL_HIDDEN_CALLBACK(int) pdmR3DevHlpTracing_IoPortMap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts, RTIOPORT Port)
213{
214 PDMDEV_ASSERT_DEVINS(pDevIns);
215 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x Port=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts, Port));
216 PVM pVM = pDevIns->Internal.s.pVMR3;
217 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
218
219 int rc = IOMR3IoPortMap(pVM, pDevIns, hIoPorts, Port);
220 DBGFTracerEvtIoPortMap(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, hIoPorts, Port);
221
222 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
223 return rc;
224}
225
226
227/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortUnmap} */
228DECL_HIDDEN_CALLBACK(int) pdmR3DevHlpTracing_IoPortUnmap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts)
229{
230 PDMDEV_ASSERT_DEVINS(pDevIns);
231 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts));
232 PVM pVM = pDevIns->Internal.s.pVMR3;
233 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
234
235 int rc = IOMR3IoPortUnmap(pVM, pDevIns, hIoPorts);
236 DBGFTracerEvtIoPortUnmap(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, hIoPorts);
237
238 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
239 return rc;
240}
241
242
243/** @interface_method_impl{PDMDEVHLPR3,pfnMmioCreateEx} */
244DECL_HIDDEN_CALLBACK(int)
245pdmR3DevHlpTracing_MmioCreateEx(PPDMDEVINS pDevIns, RTGCPHYS cbRegion,
246 uint32_t fFlags, PPDMPCIDEV pPciDev, uint32_t iPciRegion,
247 PFNIOMMMIONEWWRITE pfnWrite, PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill,
248 void *pvUser, const char *pszDesc, PIOMMMIOHANDLE phRegion)
249{
250 PDMDEV_ASSERT_DEVINS(pDevIns);
251 LogFlow(("pdmR3DevHlp_MmioCreateEx: caller='%s'/%d: cbRegion=%#RGp fFlags=%#x pPciDev=%p iPciRegion=%#x pfnWrite=%p pfnRead=%p pfnFill=%p pvUser=%p pszDesc=%p:{%s} phRegion=%p\n",
252 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, fFlags, pPciDev, iPciRegion, pfnWrite, pfnRead, pfnFill, pvUser, pszDesc, pszDesc, phRegion));
253 PVM pVM = pDevIns->Internal.s.pVMR3;
254 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
255 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
256
257 /* HACK ALERT! Round the size up to page size. The PCI bus should do something similar before mapping it. */
258 /** @todo It's possible we need to do dummy MMIO fill-in of the PCI bus or
259 * guest adds more alignment to an region. */
260 cbRegion = RT_ALIGN_T(cbRegion, PAGE_SIZE, RTGCPHYS);
261
262 int rc = VINF_SUCCESS;
263 if (pDevIns->Internal.s.idxDbgfTraceTrackNext < pDevIns->Internal.s.cDbgfTraceTrackMax)
264 {
265 PPDMDEVINSDBGFTRACK pTrack = &pDevIns->Internal.s.paDbgfTraceTrack[pDevIns->Internal.s.idxDbgfTraceTrackNext];
266
267 rc = IOMR3MmioCreate(pVM, pDevIns, cbRegion, fFlags, pPciDev, iPciRegion,
268 pfnWrite ? pdmR3DevHlpTracing_MmioWrite : NULL,
269 pfnRead ? pdmR3DevHlpTracing_MmioRead : NULL,
270 pfnFill ? pdmR3DevHlpTracing_MmioFill : NULL,
271 pTrack, pszDesc, phRegion);
272 if (RT_SUCCESS(rc))
273 {
274 pTrack->fMmio = true;
275 pTrack->pvUser = pvUser;
276 pTrack->u.Mmio.hMmioRegion = *phRegion;
277 pTrack->u.Mmio.pfnWrite = pfnWrite;
278 pTrack->u.Mmio.pfnRead = pfnRead;
279 pTrack->u.Mmio.pfnFill = pfnFill;
280 pDevIns->Internal.s.idxDbgfTraceTrackNext++;
281 DBGFR3TracerEvtMmioCreate(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, *phRegion, cbRegion, fFlags, iPciRegion);
282 }
283 }
284 else
285 rc = VERR_OUT_OF_RESOURCES;
286
287 LogFlow(("pdmR3DevHlp_MmioCreateEx: caller='%s'/%d: returns %Rrc (*phRegion=%#x)\n",
288 pDevIns->pReg->szName, pDevIns->iInstance, rc, *phRegion));
289 return rc;
290}
291
292
293/** @interface_method_impl{PDMDEVHLPR3,pfnMmioMap} */
294DECL_HIDDEN_CALLBACK(int) pdmR3DevHlpTracing_MmioMap(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS GCPhys)
295{
296 PDMDEV_ASSERT_DEVINS(pDevIns);
297 LogFlow(("pdmR3DevHlp_MmioMap: caller='%s'/%d: hRegion=%#x GCPhys=%#RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion, GCPhys));
298 PVM pVM = pDevIns->Internal.s.pVMR3;
299 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
300
301 int rc = IOMR3MmioMap(pVM, pDevIns, hRegion, GCPhys);
302 DBGFTracerEvtMmioMap(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, hRegion, GCPhys);
303
304 LogFlow(("pdmR3DevHlp_MmioMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
305 return rc;
306}
307
308
309/** @interface_method_impl{PDMDEVHLPR3,pfnMmioUnmap} */
310DECL_HIDDEN_CALLBACK(int) pdmR3DevHlpTracing_MmioUnmap(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)
311{
312 PDMDEV_ASSERT_DEVINS(pDevIns);
313 LogFlow(("pdmR3DevHlp_MmioUnmap: caller='%s'/%d: hRegion=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
314 PVM pVM = pDevIns->Internal.s.pVMR3;
315 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
316
317 int rc = IOMR3MmioUnmap(pVM, pDevIns, hRegion);
318 DBGFTracerEvtMmioUnmap(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, hRegion);
319
320 LogFlow(("pdmR3DevHlp_MmioUnmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
321 return rc;
322}
323
324
325/** @interface_method_impl{PDMDEVHLPR3,pfnPhysRead} */
326DECL_HIDDEN_CALLBACK(int)
327pdmR3DevHlpTracing_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags)
328{
329 RT_NOREF(fFlags);
330
331 PDMDEV_ASSERT_DEVINS(pDevIns);
332 PVM pVM = pDevIns->Internal.s.pVMR3;
333 LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
334 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
335
336#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
337 if (!VM_IS_EMT(pVM))
338 {
339 char szNames[128];
340 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
341 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
342 }
343#endif
344
345 VBOXSTRICTRC rcStrict;
346 if (VM_IS_EMT(pVM))
347 rcStrict = PGMPhysRead(pVM, GCPhys, pvBuf, cbRead, PGMACCESSORIGIN_DEVICE);
348 else
349 rcStrict = PGMR3PhysReadExternal(pVM, GCPhys, pvBuf, cbRead, PGMACCESSORIGIN_DEVICE);
350 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
351
352 if (!(fFlags & PDM_DEVHLP_PHYS_RW_F_DATA_USER))
353 DBGFTracerEvtGCPhysRead(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, GCPhys, pvBuf, cbRead);
354
355 Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
356 return VBOXSTRICTRC_VAL(rcStrict);
357}
358
359
360/** @interface_method_impl{PDMDEVHLPR3,pfnPhysWrite} */
361DECL_HIDDEN_CALLBACK(int)
362pdmR3DevHlpTracing_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags)
363{
364 RT_NOREF(fFlags);
365
366 PDMDEV_ASSERT_DEVINS(pDevIns);
367 PVM pVM = pDevIns->Internal.s.pVMR3;
368 LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
369 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
370
371#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
372 if (!VM_IS_EMT(pVM))
373 {
374 char szNames[128];
375 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
376 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
377 }
378#endif
379
380 VBOXSTRICTRC rcStrict;
381 if (VM_IS_EMT(pVM))
382 rcStrict = PGMPhysWrite(pVM, GCPhys, pvBuf, cbWrite, PGMACCESSORIGIN_DEVICE);
383 else
384 rcStrict = PGMR3PhysWriteExternal(pVM, GCPhys, pvBuf, cbWrite, PGMACCESSORIGIN_DEVICE);
385 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
386
387 if (!(fFlags & PDM_DEVHLP_PHYS_RW_F_DATA_USER))
388 DBGFTracerEvtGCPhysWrite(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, GCPhys, pvBuf, cbWrite);
389
390 Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
391 return VBOXSTRICTRC_VAL(rcStrict);
392}
393
394
395/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysRead} */
396DECL_HIDDEN_CALLBACK(int)
397pdmR3DevHlpTracing_PCIPhysRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags)
398{
399 PDMDEV_ASSERT_DEVINS(pDevIns);
400 if (!pPciDev) /* NULL is an alias for the default PCI device. */
401 pPciDev = pDevIns->apPciDevs[0];
402 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
403 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
404
405#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
406 /*
407 * Just check the busmaster setting here and forward the request to the generic read helper.
408 */
409 if (PCIDevIsBusmaster(pPciDev))
410 { /* likely */ }
411 else
412 {
413 Log(("pdmR3DevHlp_PCIPhysRead: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbRead=%#zx\n",
414 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbRead));
415 memset(pvBuf, 0xff, cbRead);
416 return VERR_PDM_NOT_PCI_BUS_MASTER;
417 }
418#endif
419
420#ifdef VBOX_WITH_IOMMU_AMD
421 /** @todo IOMMU: Optimize/re-organize things here later. */
422 PVM pVM = pDevIns->Internal.s.pVMR3;
423 PPDMIOMMU pIommu = &pVM->pdm.s.aIommus[0];
424 PPDMDEVINS pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
425 if ( pDevInsIommu
426 && pDevInsIommu != pDevIns)
427 {
428 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
429 Assert(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
430 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
431
432 RTGCPHYS GCPhysOut;
433 uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
434 int rc = pIommu->pfnMemRead(pDevInsIommu, uDevId, GCPhys, cbRead, &GCPhysOut);
435 if (RT_SUCCESS(rc))
436 GCPhys = GCPhysOut;
437 else
438 {
439 Log(("pdmR3DevHlp_PCIPhysRead: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
440 cbRead, rc));
441 return rc;
442 }
443
444 GCPhys = GCPhysOut;
445 }
446#endif
447
448 return pDevIns->pHlpR3->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead, fFlags);
449}
450
451
452/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysWrite} */
453DECL_HIDDEN_CALLBACK(int)
454pdmR3DevHlpTracing_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags)
455{
456 PDMDEV_ASSERT_DEVINS(pDevIns);
457 if (!pPciDev) /* NULL is an alias for the default PCI device. */
458 pPciDev = pDevIns->apPciDevs[0];
459 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
460 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
461
462#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
463 /*
464 * Just check the busmaster setting here and forward the request to the generic read helper.
465 */
466 if (PCIDevIsBusmaster(pPciDev))
467 { /* likely */ }
468 else
469 {
470 Log(("pdmR3DevHlp_PCIPhysWrite: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n",
471 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
472 return VERR_PDM_NOT_PCI_BUS_MASTER;
473 }
474#endif
475
476#ifdef VBOX_WITH_IOMMU_AMD
477 /** @todo IOMMU: Optimize/re-organize things here later. */
478 PVM pVM = pDevIns->Internal.s.pVMR3;
479 PPDMIOMMU pIommu = &pVM->pdm.s.aIommus[0];
480 PPDMDEVINS pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
481 if ( pDevInsIommu
482 && pDevInsIommu != pDevIns)
483 {
484 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
485 Assert(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
486 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
487
488 RTGCPHYS GCPhysOut;
489 uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
490 int rc = pIommu->pfnMemWrite(pDevInsIommu, uDevId, GCPhys, cbWrite, &GCPhysOut);
491 if (RT_SUCCESS(rc))
492 GCPhys = GCPhysOut;
493 else
494 {
495 Log(("pdmR3DevHlp_PCIPhysRead: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
496 cbWrite, rc));
497 return rc;
498 }
499
500 GCPhys = GCPhysOut;
501 }
502#endif
503
504 return pDevIns->pHlpR3->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite, fFlags);
505}
506
507
508/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrq} */
509DECL_HIDDEN_CALLBACK(void) pdmR3DevHlpTracing_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
510{
511 PDMDEV_ASSERT_DEVINS(pDevIns);
512 if (!pPciDev) /* NULL is an alias for the default PCI device. */
513 pPciDev = pDevIns->apPciDevs[0];
514 AssertReturnVoid(pPciDev);
515 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
516 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
517 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
518
519 /*
520 * Validate input.
521 */
522 Assert(iIrq == 0);
523 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
524
525 /*
526 * Must have a PCI device registered!
527 */
528 PVM pVM = pDevIns->Internal.s.pVMR3;
529 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
530 AssertReturnVoid(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
531 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
532
533 DBGFTracerEvtIrq(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, iIrq, iLevel);
534
535 pdmLock(pVM);
536 uint32_t uTagSrc;
537 if (iLevel & PDM_IRQ_LEVEL_HIGH)
538 {
539 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
540 if (iLevel == PDM_IRQ_LEVEL_HIGH)
541 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
542 else
543 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
544 }
545 else
546 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
547
548 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel, uTagSrc);
549
550 if (iLevel == PDM_IRQ_LEVEL_LOW)
551 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
552 pdmUnlock(pVM);
553
554 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
555}
556
557
558/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrqNoWait} */
559DECL_HIDDEN_CALLBACK(void) pdmR3DevHlpTracing_PCISetIrqNoWait(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
560{
561 pdmR3DevHlpTracing_PCISetIrq(pDevIns, pPciDev, iIrq, iLevel);
562}
563
564
565/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrq} */
566DECL_HIDDEN_CALLBACK(void) pdmR3DevHlpTracing_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
567{
568 PDMDEV_ASSERT_DEVINS(pDevIns);
569 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
570
571 /*
572 * Validate input.
573 */
574 Assert(iIrq < 16);
575 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
576
577 PVM pVM = pDevIns->Internal.s.pVMR3;
578
579 DBGFTracerEvtIrq(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, iIrq, iLevel);
580
581 /*
582 * Do the job.
583 */
584 pdmLock(pVM);
585 uint32_t uTagSrc;
586 if (iLevel & PDM_IRQ_LEVEL_HIGH)
587 {
588 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
589 if (iLevel == PDM_IRQ_LEVEL_HIGH)
590 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
591 else
592 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
593 }
594 else
595 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
596
597 PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */
598
599 if (iLevel == PDM_IRQ_LEVEL_LOW)
600 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
601 pdmUnlock(pVM);
602
603 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
604}
605
606
607/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrqNoWait} */
608DECL_HIDDEN_CALLBACK(void) pdmR3DevHlpTracing_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
609{
610 pdmR3DevHlpTracing_ISASetIrq(pDevIns, iIrq, iLevel);
611}
612
613
614/** @} */
615
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