VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/IOM.cpp

Last change on this file was 103152, checked in by vboxsync, 4 months ago

VMM/IOM: Enable I/O port info handlers for the ARMv8 target because it is actually used for PCI devices, bugref:10383

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 19.7 KB
RevLine 
[23]1/* $Id: IOM.cpp 103152 2024-01-31 15:43:28Z vboxsync $ */
[1]2/** @file
3 * IOM - Input / Output Monitor.
4 */
5
6/*
[98103]7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
[1]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
[1]26 */
27
28
[12703]29/** @page pg_iom IOM - The Input / Output Monitor
[1]30 *
31 * The input/output monitor will handle I/O exceptions routing them to the
[12721]32 * appropriate device. It implements an API to register and deregister virtual
33 * I/0 port handlers and memory mapped I/O handlers. A handler is PDM devices
34 * and a set of callback functions.
[1]35 *
[13005]36 * @see grp_iom
[1]37 *
[13005]38 *
[12721]39 * @section sec_iom_rawmode Raw-Mode
[1]40 *
[12721]41 * In raw-mode I/O port access is trapped (\#GP(0)) by ensuring that the actual
42 * IOPL is 0 regardless of what the guest IOPL is. The \#GP handler use the
[33540]43 * disassembler (DIS) to figure which instruction caused it (there are a number
[12721]44 * of instructions in addition to the I/O ones) and if it's an I/O port access
[40442]45 * it will hand it to IOMRCIOPortHandler (via EMInterpretPortIO).
46 * IOMRCIOPortHandler will lookup the port in the AVL tree of registered
[12721]47 * handlers. If found, the handler will be called otherwise default action is
48 * taken. (Default action is to write into the void and read all set bits.)
[1]49 *
[33540]50 * Memory Mapped I/O (MMIO) is implemented as a slightly special case of PGM
[12721]51 * access handlers. An MMIO range is registered with IOM which then registers it
52 * with the PGM access handler sub-system. The access handler catches all
53 * access and will be called in the context of a \#PF handler. In RC and R0 this
[55896]54 * handler is iomMmioPfHandler while in ring-3 it's iomR3MmioHandler (although
55 * in ring-3 there can be alternative ways). iomMmioPfHandler will attempt to
56 * emulate the instruction that is doing the access and pass the corresponding
57 * reads / writes to the device.
[12721]58 *
[33540]59 * Emulating I/O port access is less complex and should be slightly faster than
[12721]60 * emulating MMIO, so in most cases we should encourage the OS to use port I/O.
[33540]61 * Devices which are frequently accessed should register GC handlers to speed up
[12721]62 * execution.
63 *
64 *
[43387]65 * @section sec_iom_hm Hardware Assisted Virtualization Mode
[12721]66 *
67 * When running in hardware assisted virtualization mode we'll be doing much the
68 * same things as in raw-mode. The main difference is that we're running in the
69 * host ring-0 context and that we don't get faults (\#GP(0) and \#PG) but
70 * exits.
71 *
72 *
73 * @section sec_iom_rem Recompiled Execution Mode
74 *
75 * When running in the recompiler things are different. I/O port access is
76 * handled by calling IOMIOPortRead and IOMIOPortWrite directly. While MMIO can
77 * be handled in one of two ways. The normal way is that we have a registered a
78 * special RAM range with the recompiler and in the three callbacks (for byte,
79 * word and dword access) we call IOMMMIORead and IOMMMIOWrite directly. The
80 * alternative ways that the physical memory access which goes via PGM will take
[55896]81 * care of it by calling iomR3MmioHandler via the PGM access handler machinery
[12721]82 * - this shouldn't happen but it is an alternative...
83 *
84 *
85 * @section sec_iom_other Other Accesses
86 *
87 * I/O ports aren't really exposed in any other way, unless you count the
88 * instruction interpreter in EM, but that's just what we're doing in the
[35312]89 * raw-mode \#GP(0) case really. Now, it's possible to call IOMIOPortRead and
[12721]90 * IOMIOPortWrite directly to talk to a device, but this is really bad behavior
[35312]91 * and should only be done as temporary hacks (the PC BIOS device used to setup
92 * the CMOS this way back in the dark ages).
[12721]93 *
94 * MMIO has similar direct routes as the I/O ports and these shouldn't be used
95 * for the same reasons and with the same restrictions. OTOH since MMIO is
96 * mapped into the physical memory address space, it can be accessed in a number
97 * of ways thru PGM.
98 *
[60852]99 *
100 * @section sec_iom_logging Logging Levels
101 *
102 * Following assignments:
103 * - Level 5 is used for defering I/O port and MMIO writes to ring-3.
104 *
[1]105 */
106
[44850]107/** @todo MMIO - simplifying the device end.
108 * - Add a return status for doing DBGFSTOP on access where there are no known
109 * registers.
110 * -
111 *
112 * */
[1]113
[44850]114
[57358]115/*********************************************************************************************************************************
116* Header Files *
117*********************************************************************************************************************************/
[1]118#define LOG_GROUP LOG_GROUP_IOM
[35346]119#include <VBox/vmm/iom.h>
120#include <VBox/vmm/cpum.h>
121#include <VBox/vmm/pgm.h>
[1]122#include <VBox/sup.h>
[45808]123#include <VBox/vmm/hm.h>
[35346]124#include <VBox/vmm/mm.h>
125#include <VBox/vmm/stam.h>
126#include <VBox/vmm/dbgf.h>
127#include <VBox/vmm/pdmapi.h>
128#include <VBox/vmm/pdmdev.h>
[1]129#include "IOMInternal.h"
[35346]130#include <VBox/vmm/vm.h>
[1]131
132#include <VBox/param.h>
133#include <iprt/assert.h>
134#include <iprt/alloc.h>
135#include <iprt/string.h>
136#include <VBox/log.h>
137#include <VBox/err.h>
138
139
[37424]140
[1]141/**
142 * Initializes the IOM.
143 *
144 * @returns VBox status code.
[58122]145 * @param pVM The cross context VM structure.
[1]146 */
[39111]147VMMR3_INT_DECL(int) IOMR3Init(PVM pVM)
[1]148{
149 LogFlow(("IOMR3Init:\n"));
150
151 /*
152 * Assert alignment and sizes.
153 */
[19716]154 AssertCompileMemberAlignment(VM, iom.s, 32);
155 AssertCompile(sizeof(pVM->iom.s) <= sizeof(pVM->iom.padding));
[37467]156 AssertCompileMemberAlignment(IOM, CritSect, sizeof(uintptr_t));
[1]157
158 /*
[19470]159 * Initialize the REM critical section.
160 */
[45301]161#ifdef IOM_WITH_CRIT_SECT_RW
162 int rc = PDMR3CritSectRwInit(pVM, &pVM->iom.s.CritSect, RT_SRC_POS, "IOM Lock");
163#else
[37467]164 int rc = PDMR3CritSectInit(pVM, &pVM->iom.s.CritSect, RT_SRC_POS, "IOM Lock");
[45301]165#endif
[19470]166 AssertRCReturn(rc, rc);
167
168 /*
[81333]169 * Register the MMIO access handler type.
170 */
[93635]171 rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_MMIO, 0 /*fFlags*/,
[93650]172 iomMmioHandlerNew, "MMIO", &pVM->iom.s.hNewMmioHandlerType);
[81333]173 AssertRCReturn(rc, rc);
[55493]174
[81333]175 /*
176 * Info.
177 */
178 DBGFR3InfoRegisterInternal(pVM, "ioport", "Dumps all IOPort ranges. No arguments.", &iomR3IoPortInfo);
179 DBGFR3InfoRegisterInternal(pVM, "mmio", "Dumps all MMIO ranges. No arguments.", &iomR3MmioInfo);
180
181 /*
[82380]182 * Statistics (names are somewhat contorted to make the registration
183 * sub-trees appear at the end of each group).
[81333]184 */
[82380]185 STAM_REG(pVM, &pVM->iom.s.StatIoPortCommits, STAMTYPE_COUNTER, "/IOM/IoPortCommits", STAMUNIT_OCCURENCES, "Number of ring-3 I/O port commits.");
[92386]186 STAM_REG(pVM, &pVM->iom.s.StatIoPortIn, STAMTYPE_COUNTER, "/IOM/IoPortIN", STAMUNIT_OCCURENCES, "Number of IN instructions (attempts)");
187 STAM_REG(pVM, &pVM->iom.s.StatIoPortInS, STAMTYPE_COUNTER, "/IOM/IoPortINS", STAMUNIT_OCCURENCES, "Number of INS instructions (attempts)");
188 STAM_REG(pVM, &pVM->iom.s.StatIoPortOutS, STAMTYPE_COUNTER, "/IOM/IoPortOUT", STAMUNIT_OCCURENCES, "Number of OUT instructions (attempts)");
189 STAM_REG(pVM, &pVM->iom.s.StatIoPortOutS, STAMTYPE_COUNTER, "/IOM/IoPortOUTS", STAMUNIT_OCCURENCES, "Number of OUTS instructions (attempts)");
[81463]190
[82380]191 STAM_REG(pVM, &pVM->iom.s.StatMmioHandlerR3, STAMTYPE_COUNTER, "/IOM/MmioHandlerR3", STAMUNIT_OCCURENCES, "Number of calls to iomMmioHandlerNew from ring-3.");
192 STAM_REG(pVM, &pVM->iom.s.StatMmioHandlerR0, STAMTYPE_COUNTER, "/IOM/MmioHandlerR0", STAMUNIT_OCCURENCES, "Number of calls to iomMmioHandlerNew from ring-0.");
193 STAM_REG(pVM, &pVM->iom.s.StatMmioReadsR0ToR3, STAMTYPE_COUNTER, "/IOM/MmioR0ToR3Reads", STAMUNIT_OCCURENCES, "Number of reads deferred to ring-3.");
194 STAM_REG(pVM, &pVM->iom.s.StatMmioWritesR0ToR3, STAMTYPE_COUNTER, "/IOM/MmioR0ToR3Writes", STAMUNIT_OCCURENCES, "Number of writes deferred to ring-3.");
195 STAM_REG(pVM, &pVM->iom.s.StatMmioCommitsR0ToR3,STAMTYPE_COUNTER, "/IOM/MmioR0ToR3Commits", STAMUNIT_OCCURENCES, "Number of commits deferred to ring-3.");
[92386]196 STAM_REG(pVM, &pVM->iom.s.StatMmioPfHandler, STAMTYPE_PROFILE, "/IOM/MmioPfHandler", STAMUNIT_TICKS_PER_CALL, "Number of calls to iomMmioPfHandlerNew.");
197 STAM_REG(pVM, &pVM->iom.s.StatMmioPhysHandler, STAMTYPE_PROFILE, "/IOM/MmioPhysHandler", STAMUNIT_TICKS_PER_CALL, "Number of calls to IOMR0MmioPhysHandler.");
[82380]198 STAM_REG(pVM, &pVM->iom.s.StatMmioCommitsDirect,STAMTYPE_COUNTER, "/IOM/MmioCommitsDirect", STAMUNIT_OCCURENCES, "Number of ring-3 MMIO commits direct to handler via handle hint.");
199 STAM_REG(pVM, &pVM->iom.s.StatMmioCommitsPgm, STAMTYPE_COUNTER, "/IOM/MmioCommitsPgm", STAMUNIT_OCCURENCES, "Number of ring-3 MMIO commits via PGM.");
[92386]200 STAM_REL_REG(pVM, &pVM->iom.s.StatMmioStaleMappings, STAMTYPE_COUNTER, "/IOM/MmioMappingsStale", STAMUNIT_TICKS_PER_CALL, "Number of times iomMmioHandlerNew got a call for a remapped range at the old mapping.");
[98045]201 STAM_REL_REG(pVM, &pVM->iom.s.StatMmioTooDeepRecursion, STAMTYPE_COUNTER, "/IOM/MmioTooDeepRecursion", STAMUNIT_OCCURENCES, "Number of times iomMmioHandlerNew detected too deep recursion and took default action.");
[82380]202 STAM_REG(pVM, &pVM->iom.s.StatMmioDevLockContentionR0, STAMTYPE_COUNTER, "/IOM/MmioDevLockContentionR0", STAMUNIT_OCCURENCES, "Number of device lock contention force return to ring-3.");
[1]203
[81333]204 LogFlow(("IOMR3Init: returns VINF_SUCCESS\n"));
205 return VINF_SUCCESS;
[1]206}
207
208
209/**
[80649]210 * Called when a VM initialization stage is completed.
211 *
212 * @returns VBox status code.
213 * @param pVM The cross context VM structure.
214 * @param enmWhat The initialization state that was completed.
215 */
216VMMR3_INT_DECL(int) IOMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
217{
218#ifdef VBOX_WITH_STATISTICS
[81983]219 if (enmWhat == VMINITCOMPLETED_RING0)
[80649]220 {
[81333]221 /*
222 * Synchronize the ring-3 I/O port and MMIO statistics indices into the
223 * ring-0 tables to simplify ring-0 code. This also make sure that any
224 * later calls to grow the statistics tables will fail.
225 */
[92719]226 if (!SUPR3IsDriverless())
227 {
228 int rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_SYNC_STATS_INDICES, 0, NULL);
229 AssertLogRelRCReturn(rc, rc);
230 }
[81333]231
232 /*
233 * Register I/O port and MMIO stats now that we're done registering MMIO
234 * regions and won't grow the table again.
235 */
[80649]236 for (uint32_t i = 0; i < pVM->iom.s.cIoPortRegs; i++)
237 {
238 PIOMIOPORTENTRYR3 pRegEntry = &pVM->iom.s.paIoPortRegs[i];
239 if ( pRegEntry->fMapped
240 && pRegEntry->idxStats != UINT16_MAX)
241 iomR3IoPortRegStats(pVM, pRegEntry);
242 }
[81333]243
244 for (uint32_t i = 0; i < pVM->iom.s.cMmioRegs; i++)
245 {
246 PIOMMMIOENTRYR3 pRegEntry = &pVM->iom.s.paMmioRegs[i];
247 if ( pRegEntry->fMapped
248 && pRegEntry->idxStats != UINT16_MAX)
249 iomR3MmioRegStats(pVM, pRegEntry);
250 }
[80649]251 }
252#else
253 RT_NOREF(pVM, enmWhat);
254#endif
[92719]255
256 /*
257 * Freeze I/O port and MMIO registrations.
258 */
259 pVM->iom.s.fIoPortsFrozen = true;
260 pVM->iom.s.fMmioFrozen = true;
[80649]261 return VINF_SUCCESS;
262}
263
264
265/**
[1]266 * The VM is being reset.
267 *
[58122]268 * @param pVM The cross context VM structure.
[1]269 */
[39111]270VMMR3_INT_DECL(void) IOMR3Reset(PVM pVM)
[1]271{
[82313]272 RT_NOREF(pVM);
[1]273}
274
275
276/**
277 * Applies relocations to data and code managed by this
278 * component. This function will be called at init and
279 * whenever the VMM need to relocate it self inside the GC.
280 *
281 * The IOM will update the addresses used by the switcher.
282 *
[58122]283 * @param pVM The cross context VM structure.
[1]284 * @param offDelta Relocation delta relative to old location.
285 */
[39111]286VMMR3_INT_DECL(void) IOMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
[1]287{
[80090]288 RT_NOREF(pVM, offDelta);
[1]289}
290
291/**
292 * Terminates the IOM.
293 *
294 * Termination means cleaning up and freeing all resources,
295 * the VM it self is at this point powered off or suspended.
296 *
297 * @returns VBox status code.
[58122]298 * @param pVM The cross context VM structure.
[1]299 */
[39111]300VMMR3_INT_DECL(int) IOMR3Term(PVM pVM)
[1]301{
302 /*
303 * IOM is not owning anything but automatically freed resources,
304 * so there's nothing to do here.
305 */
[39078]306 NOREF(pVM);
[1]307 return VINF_SUCCESS;
308}
309
[80641]310
311/**
[60847]312 * Handles the unlikely and probably fatal merge cases.
313 *
314 * @returns Merged status code.
315 * @param rcStrict Current EM status code.
316 * @param rcStrictCommit The IOM I/O or MMIO write commit status to merge
317 * with @a rcStrict.
318 * @param rcIom For logging purposes only.
319 * @param pVCpu The cross context virtual CPU structure of the
320 * calling EMT. For logging purposes.
321 */
322DECL_NO_INLINE(static, VBOXSTRICTRC) iomR3MergeStatusSlow(VBOXSTRICTRC rcStrict, VBOXSTRICTRC rcStrictCommit,
323 int rcIom, PVMCPU pVCpu)
324{
325 if (RT_FAILURE_NP(rcStrict))
326 return rcStrict;
327
328 if (RT_FAILURE_NP(rcStrictCommit))
329 return rcStrictCommit;
330
331 if (rcStrict == rcStrictCommit)
332 return rcStrictCommit;
333
334 AssertLogRelMsgFailed(("rcStrictCommit=%Rrc rcStrict=%Rrc IOPort={%#06x<-%#xx/%u} MMIO={%RGp<-%.*Rhxs} (rcIom=%Rrc)\n",
335 VBOXSTRICTRC_VAL(rcStrictCommit), VBOXSTRICTRC_VAL(rcStrict),
336 pVCpu->iom.s.PendingIOPortWrite.IOPort,
337 pVCpu->iom.s.PendingIOPortWrite.u32Value, pVCpu->iom.s.PendingIOPortWrite.cbValue,
338 pVCpu->iom.s.PendingMmioWrite.GCPhys,
339 pVCpu->iom.s.PendingMmioWrite.cbValue, &pVCpu->iom.s.PendingMmioWrite.abValue[0], rcIom));
340 return VERR_IOM_FF_STATUS_IPE;
341}
342
343
344/**
345 * Helper for IOMR3ProcessForceFlag.
346 *
347 * @returns Merged status code.
348 * @param rcStrict Current EM status code.
349 * @param rcStrictCommit The IOM I/O or MMIO write commit status to merge
350 * with @a rcStrict.
351 * @param rcIom Either VINF_IOM_R3_IOPORT_COMMIT_WRITE or
352 * VINF_IOM_R3_MMIO_COMMIT_WRITE.
353 * @param pVCpu The cross context virtual CPU structure of the
354 * calling EMT.
355 */
356DECLINLINE(VBOXSTRICTRC) iomR3MergeStatus(VBOXSTRICTRC rcStrict, VBOXSTRICTRC rcStrictCommit, int rcIom, PVMCPU pVCpu)
357{
358 /* Simple. */
359 if (RT_LIKELY(rcStrict == rcIom || rcStrict == VINF_EM_RAW_TO_R3 || rcStrict == VINF_SUCCESS))
360 return rcStrictCommit;
361
[60908]362 if (RT_LIKELY(rcStrictCommit == VINF_SUCCESS))
363 return rcStrict;
364
[60847]365 /* EM scheduling status codes. */
366 if (RT_LIKELY( rcStrict >= VINF_EM_FIRST
367 && rcStrict <= VINF_EM_LAST))
368 {
369 if (RT_LIKELY( rcStrictCommit >= VINF_EM_FIRST
370 && rcStrictCommit <= VINF_EM_LAST))
371 return rcStrict < rcStrictCommit ? rcStrict : rcStrictCommit;
372 }
373
374 /* Unlikely */
375 return iomR3MergeStatusSlow(rcStrict, rcStrictCommit, rcIom, pVCpu);
376}
377
378
379/**
380 * Called by force-flag handling code when VMCPU_FF_IOM is set.
381 *
382 * @returns Merge between @a rcStrict and what the commit operation returned.
383 * @param pVM The cross context VM structure.
384 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
385 * @param rcStrict The status code returned by ring-0 or raw-mode.
386 * @thread EMT(pVCpu)
387 *
388 * @remarks The VMCPU_FF_IOM flag is handled before the status codes by EM, so
389 * we're very likely to see @a rcStrict set to
390 * VINF_IOM_R3_IOPORT_COMMIT_WRITE and VINF_IOM_R3_MMIO_COMMIT_WRITE
391 * here.
392 */
393VMMR3_INT_DECL(VBOXSTRICTRC) IOMR3ProcessForceFlag(PVM pVM, PVMCPU pVCpu, VBOXSTRICTRC rcStrict)
394{
395 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_IOM);
396 Assert(pVCpu->iom.s.PendingIOPortWrite.cbValue || pVCpu->iom.s.PendingMmioWrite.cbValue);
397
398 if (pVCpu->iom.s.PendingIOPortWrite.cbValue)
399 {
[60852]400 Log5(("IOM: Dispatching pending I/O port write: %#x LB %u -> %RTiop\n", pVCpu->iom.s.PendingIOPortWrite.u32Value,
[72249]401 pVCpu->iom.s.PendingIOPortWrite.cbValue, pVCpu->iom.s.PendingIOPortWrite.IOPort));
[81463]402 STAM_COUNTER_INC(&pVM->iom.s.StatIoPortCommits);
[60847]403 VBOXSTRICTRC rcStrictCommit = IOMIOPortWrite(pVM, pVCpu, pVCpu->iom.s.PendingIOPortWrite.IOPort,
404 pVCpu->iom.s.PendingIOPortWrite.u32Value,
405 pVCpu->iom.s.PendingIOPortWrite.cbValue);
406 pVCpu->iom.s.PendingIOPortWrite.cbValue = 0;
407 rcStrict = iomR3MergeStatus(rcStrict, rcStrictCommit, VINF_IOM_R3_IOPORT_COMMIT_WRITE, pVCpu);
408 }
409
410
411 if (pVCpu->iom.s.PendingMmioWrite.cbValue)
412 {
[60852]413 Log5(("IOM: Dispatching pending MMIO write: %RGp LB %#x\n",
414 pVCpu->iom.s.PendingMmioWrite.GCPhys, pVCpu->iom.s.PendingMmioWrite.cbValue));
[81436]415
416 /* Use new MMIO handle hint and bypass PGM if it still looks right. */
417 size_t idxMmioRegionHint = pVCpu->iom.s.PendingMmioWrite.idxMmioRegionHint;
418 if (idxMmioRegionHint < pVM->iom.s.cMmioRegs)
419 {
420 PIOMMMIOENTRYR3 pRegEntry = &pVM->iom.s.paMmioRegs[idxMmioRegionHint];
421 RTGCPHYS const GCPhysMapping = pRegEntry->GCPhysMapping;
422 RTGCPHYS const offRegion = pVCpu->iom.s.PendingMmioWrite.GCPhys - GCPhysMapping;
423 if (offRegion < pRegEntry->cbRegion && GCPhysMapping != NIL_RTGCPHYS)
424 {
[81463]425 STAM_COUNTER_INC(&pVM->iom.s.StatMmioCommitsDirect);
[81462]426 VBOXSTRICTRC rcStrictCommit = iomR3MmioCommitWorker(pVM, pVCpu, pRegEntry, offRegion);
427 pVCpu->iom.s.PendingMmioWrite.cbValue = 0;
428 return iomR3MergeStatus(rcStrict, rcStrictCommit, VINF_IOM_R3_MMIO_COMMIT_WRITE, pVCpu);
[81436]429 }
430 }
431
[81462]432 /* Fall back on PGM. */
[81463]433 STAM_COUNTER_INC(&pVM->iom.s.StatMmioCommitsPgm);
[60847]434 VBOXSTRICTRC rcStrictCommit = PGMPhysWrite(pVM, pVCpu->iom.s.PendingMmioWrite.GCPhys,
435 pVCpu->iom.s.PendingMmioWrite.abValue, pVCpu->iom.s.PendingMmioWrite.cbValue,
436 PGMACCESSORIGIN_IOM);
[60852]437 pVCpu->iom.s.PendingMmioWrite.cbValue = 0;
[60847]438 rcStrict = iomR3MergeStatus(rcStrict, rcStrictCommit, VINF_IOM_R3_MMIO_COMMIT_WRITE, pVCpu);
439 }
440
441 return rcStrict;
442}
443
444
445/**
[58903]446 * Notification from DBGF that the number of active I/O port or MMIO
447 * breakpoints has change.
448 *
449 * For performance reasons, IOM will only call DBGF before doing I/O and MMIO
450 * accesses where there are armed breakpoints.
451 *
452 * @param pVM The cross context VM structure.
[58909]453 * @param fPortIo True if there are armed I/O port breakpoints.
454 * @param fMmio True if there are armed MMIO breakpoints.
[58903]455 */
[58909]456VMMR3_INT_DECL(void) IOMR3NotifyBreakpointCountChange(PVM pVM, bool fPortIo, bool fMmio)
[58903]457{
458 /** @todo I/O breakpoints. */
[62643]459 RT_NOREF3(pVM, fPortIo, fMmio);
[58903]460}
461
462
463/**
464 * Notification from DBGF that an event has been enabled or disabled.
465 *
466 * For performance reasons, IOM may cache the state of events it implements.
467 *
468 * @param pVM The cross context VM structure.
469 * @param enmEvent The event.
470 * @param fEnabled The new state.
471 */
472VMMR3_INT_DECL(void) IOMR3NotifyDebugEventChange(PVM pVM, DBGFEVENT enmEvent, bool fEnabled)
473{
474 /** @todo IOM debug events. */
[62643]475 RT_NOREF3(pVM, enmEvent, fEnabled);
[58903]476}
477
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use