VirtualBox

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

Last change on this file since 84826 was 84826, checked in by vboxsync, 5 years ago

AMD IOMMU: bugref:9654 PDM interface changes for supplying bus:device:function for devices' initiating PCI interrupts and MSIs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.3 KB
Line 
1/* $Id: PDMDevHlpTracing.cpp 84826 2020-06-15 08:20:40Z 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} */
164DECLHIDDEN(DECLCALLBACK(int)) pdmR3DevHlpTracing_IoPortCreateEx(PPDMDEVINS pDevIns, RTIOPORT cPorts, uint32_t fFlags, PPDMPCIDEV pPciDev,
165 uint32_t iPciRegion, PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
166 PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr, RTR3PTR pvUser,
167 const char *pszDesc, PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts)
168{
169 PDMDEV_ASSERT_DEVINS(pDevIns);
170 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",
171 pDevIns->pReg->szName, pDevIns->iInstance, cPorts, fFlags, pPciDev, iPciRegion, pfnOut, pfnIn, pfnOutStr, pfnInStr,
172 pvUser, pszDesc, pszDesc, paExtDescs, phIoPorts));
173 PVM pVM = pDevIns->Internal.s.pVMR3;
174 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
175 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
176
177 int rc = VINF_SUCCESS;
178 if (pDevIns->Internal.s.idxDbgfTraceTrackNext < pDevIns->Internal.s.cDbgfTraceTrackMax)
179 {
180 PPDMDEVINSDBGFTRACK pTrack = &pDevIns->Internal.s.paDbgfTraceTrack[pDevIns->Internal.s.idxDbgfTraceTrackNext];
181
182 rc = IOMR3IoPortCreate(pVM, pDevIns, cPorts, fFlags, pPciDev, iPciRegion,
183 pfnOut ? pdmR3DevHlpTracing_IoPortNewOut : NULL,
184 pfnIn ? pdmR3DevHlpTracing_IoPortNewIn : NULL,
185 pfnOutStr ? pdmR3DevHlpTracing_IoPortNewOutStr : NULL,
186 pfnInStr ? pdmR3DevHlpTracing_IoPortNewInStr : NULL,
187 pTrack, pszDesc, paExtDescs, phIoPorts);
188 if (RT_SUCCESS(rc))
189 {
190 pTrack->fMmio = false;
191 pTrack->pvUser = pvUser;
192 pTrack->u.IoPort.hIoPorts = *phIoPorts;
193 pTrack->u.IoPort.pfnOut = pfnOut;
194 pTrack->u.IoPort.pfnIn = pfnIn;
195 pTrack->u.IoPort.pfnOutStr = pfnOutStr;
196 pTrack->u.IoPort.pfnInStr = pfnInStr;
197 pDevIns->Internal.s.idxDbgfTraceTrackNext++;
198 DBGFR3TracerEvtIoPortCreate(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, *phIoPorts, cPorts, fFlags, iPciRegion);
199 }
200 }
201 else
202 rc = VERR_OUT_OF_RESOURCES;
203
204 LogFlow(("pdmR3DevHlpTracing_IoPortCreateEx: caller='%s'/%d: returns %Rrc (*phIoPorts=%#x)\n",
205 pDevIns->pReg->szName, pDevIns->iInstance, rc, *phIoPorts));
206 return rc;
207}
208
209
210/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortMap} */
211DECLHIDDEN(DECLCALLBACK(int)) pdmR3DevHlpTracing_IoPortMap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts, RTIOPORT Port)
212{
213 PDMDEV_ASSERT_DEVINS(pDevIns);
214 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x Port=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts, Port));
215 PVM pVM = pDevIns->Internal.s.pVMR3;
216 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
217
218 int rc = IOMR3IoPortMap(pVM, pDevIns, hIoPorts, Port);
219 DBGFTracerEvtIoPortMap(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, hIoPorts, Port);
220
221 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
222 return rc;
223}
224
225
226/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortUnmap} */
227DECLHIDDEN(DECLCALLBACK(int)) pdmR3DevHlpTracing_IoPortUnmap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts)
228{
229 PDMDEV_ASSERT_DEVINS(pDevIns);
230 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts));
231 PVM pVM = pDevIns->Internal.s.pVMR3;
232 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
233
234 int rc = IOMR3IoPortUnmap(pVM, pDevIns, hIoPorts);
235 DBGFTracerEvtIoPortUnmap(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, hIoPorts);
236
237 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
238 return rc;
239}
240
241
242/** @interface_method_impl{PDMDEVHLPR3,pfnMmioCreateEx} */
243DECLHIDDEN(DECLCALLBACK(int)) pdmR3DevHlpTracing_MmioCreateEx(PPDMDEVINS pDevIns, RTGCPHYS cbRegion,
244 uint32_t fFlags, PPDMPCIDEV pPciDev, uint32_t iPciRegion,
245 PFNIOMMMIONEWWRITE pfnWrite, PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill,
246 void *pvUser, const char *pszDesc, PIOMMMIOHANDLE phRegion)
247{
248 PDMDEV_ASSERT_DEVINS(pDevIns);
249 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",
250 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, fFlags, pPciDev, iPciRegion, pfnWrite, pfnRead, pfnFill, pvUser, pszDesc, pszDesc, phRegion));
251 PVM pVM = pDevIns->Internal.s.pVMR3;
252 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
253 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
254
255 /* HACK ALERT! Round the size up to page size. The PCI bus should do something similar before mapping it. */
256 /** @todo It's possible we need to do dummy MMIO fill-in of the PCI bus or
257 * guest adds more alignment to an region. */
258 cbRegion = RT_ALIGN_T(cbRegion, PAGE_SIZE, RTGCPHYS);
259
260 int rc = VINF_SUCCESS;
261 if (pDevIns->Internal.s.idxDbgfTraceTrackNext < pDevIns->Internal.s.cDbgfTraceTrackMax)
262 {
263 PPDMDEVINSDBGFTRACK pTrack = &pDevIns->Internal.s.paDbgfTraceTrack[pDevIns->Internal.s.idxDbgfTraceTrackNext];
264
265 rc = IOMR3MmioCreate(pVM, pDevIns, cbRegion, fFlags, pPciDev, iPciRegion,
266 pfnWrite ? pdmR3DevHlpTracing_MmioWrite : NULL,
267 pfnRead ? pdmR3DevHlpTracing_MmioRead : NULL,
268 pfnFill ? pdmR3DevHlpTracing_MmioFill : NULL,
269 pTrack, pszDesc, phRegion);
270 if (RT_SUCCESS(rc))
271 {
272 pTrack->fMmio = true;
273 pTrack->pvUser = pvUser;
274 pTrack->u.Mmio.hMmioRegion = *phRegion;
275 pTrack->u.Mmio.pfnWrite = pfnWrite;
276 pTrack->u.Mmio.pfnRead = pfnRead;
277 pTrack->u.Mmio.pfnFill = pfnFill;
278 pDevIns->Internal.s.idxDbgfTraceTrackNext++;
279 DBGFR3TracerEvtMmioCreate(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, *phRegion, cbRegion, fFlags, iPciRegion);
280 }
281 }
282 else
283 rc = VERR_OUT_OF_RESOURCES;
284
285 LogFlow(("pdmR3DevHlp_MmioCreateEx: caller='%s'/%d: returns %Rrc (*phRegion=%#x)\n",
286 pDevIns->pReg->szName, pDevIns->iInstance, rc, *phRegion));
287 return rc;
288}
289
290
291/** @interface_method_impl{PDMDEVHLPR3,pfnMmioMap} */
292DECLHIDDEN(DECLCALLBACK(int)) pdmR3DevHlpTracing_MmioMap(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS GCPhys)
293{
294 PDMDEV_ASSERT_DEVINS(pDevIns);
295 LogFlow(("pdmR3DevHlp_MmioMap: caller='%s'/%d: hRegion=%#x GCPhys=%#RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion, GCPhys));
296 PVM pVM = pDevIns->Internal.s.pVMR3;
297 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
298
299 int rc = IOMR3MmioMap(pVM, pDevIns, hRegion, GCPhys);
300 DBGFTracerEvtMmioMap(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, hRegion, GCPhys);
301
302 LogFlow(("pdmR3DevHlp_MmioMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
303 return rc;
304}
305
306
307/** @interface_method_impl{PDMDEVHLPR3,pfnMmioUnmap} */
308DECLHIDDEN(DECLCALLBACK(int)) pdmR3DevHlpTracing_MmioUnmap(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)
309{
310 PDMDEV_ASSERT_DEVINS(pDevIns);
311 LogFlow(("pdmR3DevHlp_MmioUnmap: caller='%s'/%d: hRegion=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
312 PVM pVM = pDevIns->Internal.s.pVMR3;
313 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
314
315 int rc = IOMR3MmioUnmap(pVM, pDevIns, hRegion);
316 DBGFTracerEvtMmioUnmap(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, hRegion);
317
318 LogFlow(("pdmR3DevHlp_MmioUnmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
319 return rc;
320}
321
322
323/** @interface_method_impl{PDMDEVHLPR3,pfnPhysRead} */
324DECLHIDDEN(DECLCALLBACK(int)) pdmR3DevHlpTracing_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags)
325{
326 RT_NOREF(fFlags);
327
328 PDMDEV_ASSERT_DEVINS(pDevIns);
329 PVM pVM = pDevIns->Internal.s.pVMR3;
330 LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
331 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
332
333#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
334 if (!VM_IS_EMT(pVM))
335 {
336 char szNames[128];
337 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
338 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
339 }
340#endif
341
342 VBOXSTRICTRC rcStrict;
343 if (VM_IS_EMT(pVM))
344 rcStrict = PGMPhysRead(pVM, GCPhys, pvBuf, cbRead, PGMACCESSORIGIN_DEVICE);
345 else
346 rcStrict = PGMR3PhysReadExternal(pVM, GCPhys, pvBuf, cbRead, PGMACCESSORIGIN_DEVICE);
347 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
348
349 if (!(fFlags & PDM_DEVHLP_PHYS_RW_F_DATA_USER))
350 DBGFTracerEvtGCPhysRead(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, GCPhys, pvBuf, cbRead);
351
352 Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
353 return VBOXSTRICTRC_VAL(rcStrict);
354}
355
356
357/** @interface_method_impl{PDMDEVHLPR3,pfnPhysWrite} */
358DECLHIDDEN(DECLCALLBACK(int)) pdmR3DevHlpTracing_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags)
359{
360 RT_NOREF(fFlags);
361
362 PDMDEV_ASSERT_DEVINS(pDevIns);
363 PVM pVM = pDevIns->Internal.s.pVMR3;
364 LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
365 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
366
367#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
368 if (!VM_IS_EMT(pVM))
369 {
370 char szNames[128];
371 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
372 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
373 }
374#endif
375
376 VBOXSTRICTRC rcStrict;
377 if (VM_IS_EMT(pVM))
378 rcStrict = PGMPhysWrite(pVM, GCPhys, pvBuf, cbWrite, PGMACCESSORIGIN_DEVICE);
379 else
380 rcStrict = PGMR3PhysWriteExternal(pVM, GCPhys, pvBuf, cbWrite, PGMACCESSORIGIN_DEVICE);
381 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
382
383 if (!(fFlags & PDM_DEVHLP_PHYS_RW_F_DATA_USER))
384 DBGFTracerEvtGCPhysWrite(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, GCPhys, pvBuf, cbWrite);
385
386 Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
387 return VBOXSTRICTRC_VAL(rcStrict);
388}
389
390
391/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysRead} */
392DECLHIDDEN(DECLCALLBACK(int))
393pdmR3DevHlpTracing_PCIPhysRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags)
394{
395 PDMDEV_ASSERT_DEVINS(pDevIns);
396 if (!pPciDev) /* NULL is an alias for the default PCI device. */
397 pPciDev = pDevIns->apPciDevs[0];
398 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
399 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
400
401#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
402 /*
403 * Just check the busmaster setting here and forward the request to the generic read helper.
404 */
405 if (PCIDevIsBusmaster(pPciDev))
406 { /* likely */ }
407 else
408 {
409 Log(("pdmR3DevHlp_PCIPhysRead: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbRead=%#zx\n",
410 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbRead));
411 memset(pvBuf, 0xff, cbRead);
412 return VERR_PDM_NOT_PCI_BUS_MASTER;
413 }
414#endif
415
416#ifdef VBOX_WITH_IOMMU_AMD
417 /** @todo IOMMU: Optimize/re-organize things here later. */
418 PVM pVM = pDevIns->Internal.s.pVMR3;
419 PPDMIOMMU pIommu = &pVM->pdm.s.aIommus[0];
420 PPDMDEVINS pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
421 if ( pDevInsIommu
422 && pDevInsIommu != pDevIns)
423 {
424 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
425 Assert(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
426 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
427
428 RTGCPHYS GCPhysOut;
429 uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
430 int rc = pIommu->pfnMemRead(pDevInsIommu, uDevId, GCPhys, cbRead, &GCPhysOut);
431 if (RT_FAILURE(rc))
432 {
433 Log(("pdmR3DevHlp_PCIPhysRead: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
434 cbRead, rc));
435 return rc;
436 }
437 }
438#endif
439
440 return pDevIns->pHlpR3->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead, fFlags);
441}
442
443
444/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysWrite} */
445DECLHIDDEN(DECLCALLBACK(int))
446pdmR3DevHlpTracing_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags)
447{
448 PDMDEV_ASSERT_DEVINS(pDevIns);
449 if (!pPciDev) /* NULL is an alias for the default PCI device. */
450 pPciDev = pDevIns->apPciDevs[0];
451 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
452 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
453
454#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
455 /*
456 * Just check the busmaster setting here and forward the request to the generic read helper.
457 */
458 if (PCIDevIsBusmaster(pPciDev))
459 { /* likely */ }
460 else
461 {
462 Log(("pdmR3DevHlp_PCIPhysWrite: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n",
463 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
464 return VERR_PDM_NOT_PCI_BUS_MASTER;
465 }
466#endif
467
468#ifdef VBOX_WITH_IOMMU_AMD
469 /** @todo IOMMU: Optimize/re-organize things here later. */
470 PVM pVM = pDevIns->Internal.s.pVMR3;
471 PPDMIOMMU pIommu = &pVM->pdm.s.aIommus[0];
472 PPDMDEVINS pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
473 if ( pDevInsIommu
474 && pDevInsIommu != pDevIns)
475 {
476 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
477 Assert(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
478 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
479
480 RTGCPHYS GCPhysOut;
481 uint16_t const uDevId = PCIBDF_MAKE(pBus->iBus, pPciDev->uDevFn);
482 int rc = pIommu->pfnMemWrite(pDevInsIommu, uDevId, GCPhys, cbWrite, &GCPhysOut);
483 if (RT_FAILURE(rc))
484 {
485 Log(("pdmR3DevHlp_PCIPhysRead: IOMMU translation failed. uDevId=%#x GCPhys=%#RGp cb=%u rc=%Rrc\n", uDevId, GCPhys,
486 cbWrite, rc));
487 return rc;
488 }
489 }
490#endif
491
492 return pDevIns->pHlpR3->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite, fFlags);
493}
494
495
496/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrq} */
497DECLHIDDEN(DECLCALLBACK(void)) pdmR3DevHlpTracing_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
498{
499 PDMDEV_ASSERT_DEVINS(pDevIns);
500 if (!pPciDev) /* NULL is an alias for the default PCI device. */
501 pPciDev = pDevIns->apPciDevs[0];
502 AssertReturnVoid(pPciDev);
503 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
504 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
505 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
506
507 /*
508 * Validate input.
509 */
510 Assert(iIrq == 0);
511 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
512
513 /*
514 * Must have a PCI device registered!
515 */
516 PVM pVM = pDevIns->Internal.s.pVMR3;
517 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
518 AssertReturnVoid(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
519 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
520
521 DBGFTracerEvtIrq(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, iIrq, iLevel);
522
523 pdmLock(pVM);
524 uint32_t uTagSrc;
525 if (iLevel & PDM_IRQ_LEVEL_HIGH)
526 {
527 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
528 if (iLevel == PDM_IRQ_LEVEL_HIGH)
529 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
530 else
531 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
532 }
533 else
534 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
535
536 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel, uTagSrc);
537
538 if (iLevel == PDM_IRQ_LEVEL_LOW)
539 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
540 pdmUnlock(pVM);
541
542 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
543}
544
545
546/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrqNoWait} */
547DECLHIDDEN(DECLCALLBACK(void)) pdmR3DevHlpTracing_PCISetIrqNoWait(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
548{
549 pdmR3DevHlpTracing_PCISetIrq(pDevIns, pPciDev, iIrq, iLevel);
550}
551
552
553/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrq} */
554DECLHIDDEN(DECLCALLBACK(void)) pdmR3DevHlpTracing_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
555{
556 PDMDEV_ASSERT_DEVINS(pDevIns);
557 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
558
559 /*
560 * Validate input.
561 */
562 Assert(iIrq < 16);
563 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
564
565 PVM pVM = pDevIns->Internal.s.pVMR3;
566
567 DBGFTracerEvtIrq(pVM, pDevIns->Internal.s.hDbgfTraceEvtSrc, iIrq, iLevel);
568
569 /*
570 * Do the job.
571 */
572 pdmLock(pVM);
573 uint32_t uTagSrc;
574 if (iLevel & PDM_IRQ_LEVEL_HIGH)
575 {
576 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
577 if (iLevel == PDM_IRQ_LEVEL_HIGH)
578 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
579 else
580 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
581 }
582 else
583 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
584
585 PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */
586
587 if (iLevel == PDM_IRQ_LEVEL_LOW)
588 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
589 pdmUnlock(pVM);
590
591 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
592}
593
594
595/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrqNoWait} */
596DECLHIDDEN(DECLCALLBACK(void)) pdmR3DevHlpTracing_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
597{
598 pdmR3DevHlpTracing_ISASetIrq(pDevIns, iIrq, iLevel);
599}
600
601
602/** @} */
603
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