IOMAllMMIO.cpp revision 3c3fadf5aeb22d1e9869e5fd72bdd6b1ebd4d4ac
a23fd118e437af0a7877dd313db8fdaa3537c675yl * IOM - Input / Output Monitor - Any Context, MMIO & String I/O.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Copyright (C) 2006-2010 Oracle Corporation
a23fd118e437af0a7877dd313db8fdaa3537c675yl * This file is part of VirtualBox Open Source Edition (OSE), as
a23fd118e437af0a7877dd313db8fdaa3537c675yl * available from http://www.virtualbox.org. This file is free software;
a23fd118e437af0a7877dd313db8fdaa3537c675yl * you can redistribute it and/or modify it under the terms of the GNU
a23fd118e437af0a7877dd313db8fdaa3537c675yl * General Public License (GPL) as published by the Free Software
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Foundation, in version 2 as it comes in the "COPYING" file of the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*******************************************************************************
a23fd118e437af0a7877dd313db8fdaa3537c675yl* Header Files *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl*******************************************************************************/
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*******************************************************************************
a23fd118e437af0a7877dd313db8fdaa3537c675yl* Global Variables *
a23fd118e437af0a7877dd313db8fdaa3537c675yl*******************************************************************************/
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Array for fast recode of the operand size (1/2/4/8 bytes) to bit shift value.
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic const unsigned g_aSize2Shift[] =
a23fd118e437af0a7877dd313db8fdaa3537c675yl ~0U, /* 0 - invalid */
a23fd118e437af0a7877dd313db8fdaa3537c675yl 0, /* *1 == 2^0 */
a23fd118e437af0a7877dd313db8fdaa3537c675yl ~0U, /* 3 - invalid */
a23fd118e437af0a7877dd313db8fdaa3537c675yl ~0U, /* 5 - invalid */
a23fd118e437af0a7877dd313db8fdaa3537c675yl ~0U, /* 6 - invalid */
a23fd118e437af0a7877dd313db8fdaa3537c675yl ~0U, /* 7 - invalid */
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Macro for fast recode of the operand size (1/2/4/8 bytes) to bit shift value.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Deals with complicated MMIO writes.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Complicatd means unaligned or non-dword/qword align accesses depending on
a23fd118e437af0a7877dd313db8fdaa3537c675yl * the MMIO region's access mode flags.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @returns Strict VBox status code. Any EM scheduling status code,
a23fd118e437af0a7877dd313db8fdaa3537c675yl * VINF_IOM_HC_MMIO_WRITE, VINF_IOM_HC_MMIO_READ_WRITE or
a23fd118e437af0a7877dd313db8fdaa3537c675yl * VINF_IOM_HC_MMIO_READ may be returned.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param pVM The VM handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param pRange The range to write to.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param GCPhys The physical address to start writing.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param pvValue Where to store the value.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param cbValue The size of the value to write.
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic VBOXSTRICTRC iomMMIODoComplicatedWrite(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhys, void const *pvValue, unsigned cbValue)
a23fd118e437af0a7877dd313db8fdaa3537c675yl AssertReturn( (pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) != IOMMMIO_FLAGS_WRITE_PASSTHRU
a23fd118e437af0a7877dd313db8fdaa3537c675yl || (pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) <= IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING,
a23fd118e437af0a7877dd313db8fdaa3537c675yl AssertReturn(cbValue != 0 && cbValue <= 16, VERR_INTERNAL_ERROR_4);
a23fd118e437af0a7877dd313db8fdaa3537c675yl bool const fReadMissing = (pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) >= IOMMMIO_FLAGS_WRITE_DWORD_READ_MISSING;
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Do debug stop if requested.
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (pRange->fFlags & IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_WRITE)
a23fd118e437af0a7877dd313db8fdaa3537c675yl "Complicated write %#x byte at %RGp to %s\n", cbValue, GCPhys, R3STRING(pRange->pszDesc));
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Split and conquer.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Get the missing bits (if any).
a23fd118e437af0a7877dd313db8fdaa3537c675yl int rc2 = pRange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser),
a23fd118e437af0a7877dd313db8fdaa3537c675yl GCPhys & ~(RTGCPHYS)3, &u32MissingValue, sizeof(u32MissingValue));
a23fd118e437af0a7877dd313db8fdaa3537c675yl /** @todo What if we've split a transfer and already read
a23fd118e437af0a7877dd313db8fdaa3537c675yl * something? Since reads can have sideeffects we could be
a23fd118e437af0a7877dd313db8fdaa3537c675yl * kind of screwed here... */
a23fd118e437af0a7877dd313db8fdaa3537c675yl LogFlow(("iomMMIODoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [read]\n", GCPhys, GCPhysStart, cbValue, rc2));
a23fd118e437af0a7877dd313db8fdaa3537c675yl Log(("iomMMIODoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [read]\n", GCPhys, GCPhysStart, cbValue, rc2));
a23fd118e437af0a7877dd313db8fdaa3537c675yl AssertMsgReturn(rc2 >= VINF_EM_FIRST && rc2 <= VINF_EM_LAST, ("%Rrc\n", rc2), VERR_IPE_UNEXPECTED_INFO_STATUS);
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Merge missing and given bits.
a23fd118e437af0a7877dd313db8fdaa3537c675yl u32GivenValue = RT_MAKE_U32_FROM_U8(((uint8_t const *)pvValue)[0], ((uint8_t const *)pvValue)[1],
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Do DWORD write to the device.
a23fd118e437af0a7877dd313db8fdaa3537c675yl int rc2 = pRange->CTX_SUFF(pfnWriteCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser),
a23fd118e437af0a7877dd313db8fdaa3537c675yl /** @todo What if we've split a transfer and already read
a23fd118e437af0a7877dd313db8fdaa3537c675yl * something? Since reads can have sideeffects we could be
a23fd118e437af0a7877dd313db8fdaa3537c675yl * kind of screwed here... */
a23fd118e437af0a7877dd313db8fdaa3537c675yl LogFlow(("iomMMIODoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [write]\n", GCPhys, GCPhysStart, cbValue, rc2));
a23fd118e437af0a7877dd313db8fdaa3537c675yl Log(("iomMMIODoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [write]\n", GCPhys, GCPhysStart, cbValue, rc2));
a23fd118e437af0a7877dd313db8fdaa3537c675yl AssertMsgReturn(rc2 >= VINF_EM_FIRST && rc2 <= VINF_EM_LAST, ("%Rrc\n", rc2), VERR_IPE_UNEXPECTED_INFO_STATUS);
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Advance.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Wrapper which does the write and updates range statistics when such are enabled.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @warning RT_SUCCESS(rc=VINF_IOM_HC_MMIO_WRITE) is TRUE!
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int iomMMIODoWrite(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, const void *pvData, unsigned cb)
a23fd118e437af0a7877dd313db8fdaa3537c675yl PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, GCPhysFault, pRange);
a23fd118e437af0a7877dd313db8fdaa3537c675yl || (pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_PASSTHRU
a23fd118e437af0a7877dd313db8fdaa3537c675yl rc = pRange->CTX_SUFF(pfnWriteCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser),
a23fd118e437af0a7877dd313db8fdaa3537c675yl GCPhysFault, (void *)pvData, cb); /** @todo fix const!! */
a23fd118e437af0a7877dd313db8fdaa3537c675yl rc = iomMMIODoComplicatedWrite(pVM, pRange, GCPhysFault, pvData, cb);
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Deals with complicated MMIO reads.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Complicatd means unaligned or non-dword/qword align accesses depending on
a23fd118e437af0a7877dd313db8fdaa3537c675yl * the MMIO region's access mode flags.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @returns Strict VBox status code. Any EM scheduling status code,
a23fd118e437af0a7877dd313db8fdaa3537c675yl * VINF_IOM_HC_MMIO_READ, VINF_IOM_HC_MMIO_READ_WRITE or
a23fd118e437af0a7877dd313db8fdaa3537c675yl * VINF_IOM_HC_MMIO_WRITE may be returned.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param pVM The VM handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param pRange The range to read from.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param GCPhys The physical address to start reading.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param pvValue Where to store the value.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param cbValue The size of the value to read.
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic VBOXSTRICTRC iomMMIODoComplicatedRead(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhys, void *pvValue, unsigned cbValue)
a23fd118e437af0a7877dd313db8fdaa3537c675yl AssertReturn( (pRange->fFlags & IOMMMIO_FLAGS_READ_MODE) == IOMMMIO_FLAGS_READ_DWORD
a23fd118e437af0a7877dd313db8fdaa3537c675yl || (pRange->fFlags & IOMMMIO_FLAGS_READ_MODE) == IOMMMIO_FLAGS_READ_DWORD_QWORD,
a23fd118e437af0a7877dd313db8fdaa3537c675yl AssertReturn(cbValue != 0 && cbValue <= 16, VERR_INTERNAL_ERROR_4);
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Do debug stop if requested.
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (pRange->fFlags & IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_READ)
a23fd118e437af0a7877dd313db8fdaa3537c675yl "Complicated read %#x byte at %RGp to %s\n", cbValue, GCPhys, R3STRING(pRange->pszDesc));
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Split and conquer.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Do DWORD read from the device.
a23fd118e437af0a7877dd313db8fdaa3537c675yl int rc2 = pRange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser),
a23fd118e437af0a7877dd313db8fdaa3537c675yl /** @todo What if we've split a transfer and already read
a23fd118e437af0a7877dd313db8fdaa3537c675yl * something? Since reads can have sideeffects we could be
a23fd118e437af0a7877dd313db8fdaa3537c675yl * kind of screwed here... */
a23fd118e437af0a7877dd313db8fdaa3537c675yl LogFlow(("iomMMIODoComplicatedRead: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc\n", GCPhys, GCPhysStart, cbValue, rc2));
a23fd118e437af0a7877dd313db8fdaa3537c675yl Log(("iomMMIODoComplicatedRead: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc\n", GCPhys, GCPhysStart, cbValue, rc2));
a23fd118e437af0a7877dd313db8fdaa3537c675yl AssertMsgReturn(rc2 >= VINF_EM_FIRST && rc2 <= VINF_EM_LAST, ("%Rrc\n", rc2), VERR_IPE_UNEXPECTED_INFO_STATUS);
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Write what we've read.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Advance.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Implements VINF_IOM_MMIO_UNUSED_FF.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @returns VINF_SUCCESS.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param pvValue Where to store the zeros.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param cbValue How many bytes to read.
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int iomMMIODoReadFFs(void *pvValue, size_t cbValue)
a23fd118e437af0a7877dd313db8fdaa3537c675yl case 4: *(uint32_t *)pvValue = UINT32_C(0xffffffff); break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl case 8: *(uint64_t *)pvValue = UINT64_C(0xffffffffffffffff); break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Implements VINF_IOM_MMIO_UNUSED_00.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @returns VINF_SUCCESS.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param pvValue Where to store the zeros.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @param cbValue How many bytes to read.
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int iomMMIODoRead00s(void *pvValue, size_t cbValue)
a23fd118e437af0a7877dd313db8fdaa3537c675yl case 4: *(uint32_t *)pvValue = UINT32_C(0x00000000); break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl case 8: *(uint64_t *)pvValue = UINT64_C(0x0000000000000000); break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Wrapper which does the read and updates range statistics when such are enabled.
a23fd118e437af0a7877dd313db8fdaa3537c675ylDECLINLINE(int) iomMMIODoRead(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhys, void *pvValue, unsigned cbValue)
a23fd118e437af0a7877dd313db8fdaa3537c675yl PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, GCPhys, pRange);
rc = pRange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhys, pvValue, cbValue);
#ifdef VBOX_WITH_STATISTICS
switch (cb)
static int iomInterpretMOVxXRead(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
return rc;
static int iomInterpretMOVxXWrite(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
unsigned cb = 0;
return rc;
#ifdef IN_RC
DECLINLINE(int) iomRamWrite(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, RTGCPTR GCPtrDst, void *pvSrc, uint32_t cb)
* PGMPhysInterpretedWriteNoHandlers/PGMPhysWriteGCPtr may mess up
return PGMPhysInterpretedWriteNoHandlers(pVCpu, pCtxCore, GCPtrDst, pvSrc, cb, false /*fRaiseTrap*/);
#if defined(IOM_WITH_MOVS_SUPPORT) && 0 /* locking prevents this from working. has buggy ecx handling. */
static int iomInterpretMOVS(PVM pVM, bool fWriteAccess, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange,
#ifndef IN_RC
return VINF_EM_RAW_EMULATE_INSTR;
if (SELMGetCpuModeFromSelector(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid) == CPUMODE_16BIT)
if (!cTransfers)
return VINF_SUCCESS;
#ifdef VBOX_WITH_STATISTICS
int rc;
if (fWriteAccess)
return VINF_IOM_HC_MMIO_WRITE;
/* Access verification first; we currently can't recover properly from traps inside this instruction */
return VINF_EM_RAW_EMULATE_INSTR;
#ifdef IN_RC
while (cTransfers)
cTransfers--;
#ifdef IN_RC
return VINF_IOM_HC_MMIO_READ;
return VINF_IOM_HC_MMIO_READ;
return VINF_IOM_HC_MMIO_READ_WRITE;
while (cTransfers)
cTransfers--;
/* Access verification first; we currently can't recover properly from traps inside this instruction */
return VINF_EM_RAW_EMULATE_INSTR;
#ifdef IN_RC
while (cTransfers)
cTransfers--;
#ifdef IN_RC
return rc;
switch (enmCpuMode)
static int iomInterpretSTOS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
#ifndef IN_RC
return VINF_EM_RAW_EMULATE_INSTR;
if (!cTransfers)
return VINF_SUCCESS;
#ifdef VBOX_WITH_STATISTICS
int rc;
if (offIncrement > 0)
cTransfers--;
} while (cTransfers);
return rc;
static int iomInterpretLODS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
return rc;
static int iomInterpretCMP(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
unsigned cb = 0;
int rc;
return VINF_IOM_HC_MMIO_READ_WRITE;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return rc;
static int iomInterpretOrXorAnd(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, PFNEMULATEPARAM3 pfnEmulate)
unsigned cb = 0;
bool fAndWrite;
int rc;
#ifdef LOG_ENABLED
const char *pszInstr;
return VINF_IOM_HC_MMIO_READ_WRITE;
fAndWrite = false;
return VINF_IOM_HC_MMIO_READ_WRITE;
fAndWrite = true;
if (fAndWrite)
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return rc;
static int iomInterpretTEST(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
unsigned cb = 0;
int rc;
return VINF_IOM_HC_MMIO_READ_WRITE;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return rc;
static int iomInterpretBT(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
unsigned cbIgnored;
return rc;
static int iomInterpretXCHG(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
return VINF_IOM_HC_MMIO_READ_WRITE;
int rc;
unsigned cb = 0;
AssertMsg(rc == VINF_IOM_HC_MMIO_READ_WRITE || rc == VINF_IOM_HC_MMIO_WRITE || rc == VINF_PATM_HC_MMIO_PATCH_WRITE, ("rc=%Rrc\n", rc));
AssertMsg(rc == VINF_IOM_HC_MMIO_READ_WRITE || rc == VINF_IOM_HC_MMIO_READ || rc == VINF_PATM_HC_MMIO_PATCH_READ, ("rc=%Rrc\n", rc));
return rc;
static int iomMMIOHandler(PVM pVM, uint32_t uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault, void *pvUser)
#ifndef IN_RING3
return VINF_IOM_HC_MMIO_READ_WRITE;
#ifdef VBOX_WITH_STATISTICS
if (!pStats)
# ifdef IN_RING3
return VERR_NO_MEMORY;
return VINF_IOM_HC_MMIO_READ_WRITE;
#ifndef IN_RING3
return VINF_IOM_HC_MMIO_READ_WRITE;
return rc;
unsigned cbOp;
return rc;
case OP_MOV:
case OP_MOVZX:
case OP_MOVSX:
AssertMsg(uErrorCode == UINT32_MAX || DIS_IS_EFFECTIVE_ADDR(pDis->param1.flags) == !!(uErrorCode & X86_TRAP_PF_RW), ("flags1=%#llx/%RTbool flags2=%#llx/%RTbool ErrCd=%#x\n", pDis->param1.flags, DIS_IS_EFFECTIVE_ADDR(pDis->param1.flags), pDis->param2.flags, DIS_IS_EFFECTIVE_ADDR(pDis->param2.flags), uErrorCode));
#ifdef IOM_WITH_MOVS_SUPPORT
case OP_MOVSB:
case OP_MOVSWD:
rc = iomInterpretMOVS(pVM, !!(uErrorCode & X86_TRAP_PF_RW), pCtxCore, GCPhysFault, pDis, pRange, &pStat);
case OP_STOSB:
case OP_STOSWD:
case OP_LODSB:
case OP_LODSWD:
case OP_CMP:
case OP_AND:
case OP_OR:
case OP_XOR:
case OP_TEST:
case OP_BT:
case OP_XCHG:
switch (rc)
case VINF_IOM_HC_MMIO_READ:
case VINF_IOM_HC_MMIO_WRITE:
return rc;
VMMDECL(int) IOMMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)
VMMDECL(VBOXSTRICTRC) IOMMMIOPhysHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault)
#ifndef IN_RING3
return VINF_IOM_HC_MMIO_READ_WRITE;
VBOXSTRICTRC rcStrict = iomMMIOHandler(pVM, (uint32_t)uErrorCode, pCtxCore, GCPhysFault, iomMmioGetRange(pVM, GCPhysFault));
#ifdef IN_RING3
DECLCALLBACK(int) IOMR3MMIOHandler(PVM pVM, RTGCPHYS GCPhysFault, void *pvPhys, void *pvBuf, size_t cbBuf,
return rc;
return rc;
#ifndef IN_RING3
return VINF_IOM_HC_MMIO_WRITE;
AssertMsg(pRange, ("Handlers and page tables are out of sync or something! GCPhys=%RGp cbValue=%d\n", GCPhys, cbValue));
if (!pRange)
return VERR_INTERNAL_ERROR;
#ifdef VBOX_WITH_STATISTICS
if (!pStats)
# ifdef IN_RING3
return VERR_NO_MEMORY;
return VINF_IOM_HC_MMIO_READ;
return rc;
case VINF_SUCCESS:
Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=VINF_SUCCESS\n", GCPhys, *pu32Value, cbValue));
return rc;
#ifndef IN_RING3
case VINF_IOM_HC_MMIO_READ:
Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=%Rrc\n", GCPhys, *pu32Value, cbValue, VBOXSTRICTRC_VAL(rc)));
return rc;
case VINF_IOM_MMIO_UNUSED_00:
Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=%Rrc\n", GCPhys, *pu32Value, cbValue, VBOXSTRICTRC_VAL(rc)));
return VINF_SUCCESS;
case VINF_IOM_MMIO_UNUSED_FF:
Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=%Rrc\n", GCPhys, *pu32Value, cbValue, VBOXSTRICTRC_VAL(rc)));
return VINF_SUCCESS;
#ifndef IN_RING3
return VINF_IOM_HC_MMIO_READ;
Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=VINF_SUCCESS\n", GCPhys, *pu32Value, cbValue));
return VINF_SUCCESS;
#ifndef IN_RING3
return VINF_IOM_HC_MMIO_WRITE;
AssertMsg(pRange, ("Handlers and page tables are out of sync or something! GCPhys=%RGp cbValue=%d\n", GCPhys, cbValue));
if (!pRange)
return VERR_INTERNAL_ERROR;
#ifdef VBOX_WITH_STATISTICS
if (!pStats)
# ifdef IN_RING3
return VERR_NO_MEMORY;
return VINF_IOM_HC_MMIO_WRITE;
return rc;
#ifndef IN_RING3
Log4(("IOMMMIOWrite: GCPhys=%RGp u32=%08RX32 cb=%d rc=%Rrc\n", GCPhys, u32Value, cbValue, VBOXSTRICTRC_VAL(rc)));
return rc;
#ifndef IN_RING3
return VINF_IOM_HC_MMIO_WRITE;
Log4(("IOMMMIOWrite: GCPhys=%RGp u32=%08RX32 cb=%d rc=%Rrc\n", GCPhys, u32Value, cbValue, VINF_SUCCESS));
return VINF_SUCCESS;
* @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
* @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
VMMDECL(VBOXSTRICTRC) IOMInterpretINSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix,
return VINF_EM_RAW_EMULATE_INSTR;
#ifndef IN_RC
return VINF_EM_RAW_EMULATE_INSTR;
if (!cTransfers)
return VINF_SUCCESS;
&GCPtrDst);
return VINF_EM_RAW_EMULATE_INSTR;
/* Access verification first; we can't recover from traps inside this instruction, as the port read cannot be repeated. */
return VINF_EM_RAW_EMULATE_INSTR;
#ifdef IN_RC
cTransfers--;
#ifdef IN_RC
AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_IOM_HC_IOPORT_READ || (rcStrict >= VINF_EM_FIRST && rcStrict <= VINF_EM_LAST) || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
return rcStrict;
* @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
* @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
unsigned cb = 0;
AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
return rcStrict;
* @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
* @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
VMMDECL(VBOXSTRICTRC) IOMInterpretOUTSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix,
return VINF_EM_RAW_EMULATE_INSTR;
#ifndef IN_RC
return VINF_EM_RAW_EMULATE_INSTR;
if (!cTransfers)
return VINF_SUCCESS;
&GCPtrSrc);
return VINF_EM_RAW_EMULATE_INSTR;
/* Access verification first; we currently can't recover properly from traps inside this instruction */
return VINF_EM_RAW_EMULATE_INSTR;
#ifdef IN_RC
cTransfers--;
#ifdef IN_RC
AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_IOM_HC_IOPORT_WRITE || (rcStrict >= VINF_EM_FIRST && rcStrict <= VINF_EM_LAST) || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
return rcStrict;
* @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
* @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
unsigned cb = 0;
AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
return rcStrict;
#ifndef IN_RC
VMMDECL(int) IOMMMIOMapMMIO2Page(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysRemapped, uint64_t fPageFlags)
("Handlers and page tables are out of sync or something! GCPhys=%RGp\n", GCPhys), VERR_IOM_MMIO_RANGE_NOT_FOUND);
#if 0 /* The assertion is wrong for the PGM_SYNC_CLEAR_PGM_POOL and VINF_PGM_HANDLER_ALREADY_ALIASED cases. */
# ifdef VBOX_STRICT
return VINF_SUCCESS;
#ifdef VBOX_STRICT
("Handlers and page tables are out of sync or something! GCPhys=%RGp\n", GCPhys), VERR_IOM_MMIO_RANGE_NOT_FOUND);
return VINF_SUCCESS;
#ifdef VBOX_STRICT
("Handlers and page tables are out of sync or something! GCPhys=%RGp\n", GCPhys), VERR_IOM_MMIO_RANGE_NOT_FOUND);
#ifdef VBOX_STRICT
while (cb)
return rc;