IOMAllMMIO.cpp revision ae9ec50c70638edbb5128ccc1577e568f3fa3982
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * IOM - Input / Output Monitor - Any Context, MMIO & String I/O.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * available from http://www.virtualbox.org. This file is free software;
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * General Public License (GPL) as published by the Free Software
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * additional information or have any questions.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync/*******************************************************************************
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync* Header Files *
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync*******************************************************************************/
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync/*******************************************************************************
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync* Global Variables *
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync*******************************************************************************/
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Array for fast recode of the operand size (1/2/4/8 bytes) to bit shift value.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsyncstatic const unsigned g_aSize2Shift[] =
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync ~0, /* 0 - invalid */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync 0, /* *1 == 2^0 */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync ~0, /* 3 - invalid */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync ~0, /* 5 - invalid */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync ~0, /* 6 - invalid */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync ~0, /* 7 - invalid */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Macro for fast recode of the operand size (1/2/4/8 bytes) to bit shift value.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Wrapper which does the write and updates range statistics when such are enabled.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * @warning RT_SUCCESS(rc=VINF_IOM_HC_MMIO_WRITE) is TRUE!
db453c26f429ba8057ea92644ddd59279b9a918dvboxsyncDECLINLINE(int) iomMMIODoWrite(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, const void *pvData, unsigned cb)
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault, pRange);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync rc = pRange->CTX_SUFF(pfnWriteCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhysFault, (void *)pvData, cb); /* @todo fix const!! */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Wrapper which does the read and updates range statistics when such are enabled.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsyncDECLINLINE(int) iomMMIODoRead(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, void *pvData, unsigned cb)
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault, pRange);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync rc = pRange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhysFault, pvData, cb);
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync/** @todo r=bird: this is (probably) wrong, all bits should be set here I
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * think. */
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * Internal - statistics only.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsyncDECLINLINE(void) iomMMIOStatLength(PVM pVM, unsigned cb)
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync /* No way. */
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * MOV reg, mem (read)
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * MOVZX reg, mem (read)
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * MOVSX reg, mem (read)
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * @returns VBox status code.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * @param pVM The virtual machine.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * @param pCpu Disassembler CPU state.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * @param pRange Pointer MMIO range.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * @param GCPhysFault The GC physical address corresponding to pvFault.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsyncstatic int iomInterpretMOVxXRead(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync Assert(pRange->CTX_SUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * Get the data size from parameter 2,
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * and call the handler function to get the data.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync unsigned cb = DISGetParamSize(pCpu, &pCpu->param2);
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync AssertMsg(cb > 0 && cb <= sizeof(uint64_t), ("cb=%d\n", cb));
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync int rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &u64Data, cb);
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * Do sign extension for MOVSX.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync /** @todo checkup MOVSX implementation! */
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync /* DWORD <- BYTE */
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync /* DWORD <- WORD */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Store the result to register (parameter 1).
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync bool fRc = iomSaveDataToReg(pCpu, &pCpu->param1, pRegFrame, u64Data);
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync AssertMsg(fRc, ("Failed to store register value!\n")); NOREF(fRc);
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * MOV mem, reg|imm (write)
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * @returns VBox status code.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * @param pVM The virtual machine.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * @param pCpu Disassembler CPU state.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * @param pRange Pointer MMIO range.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * @param GCPhysFault The GC physical address corresponding to pvFault.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsyncstatic int iomInterpretMOVxXWrite(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync Assert(pRange->CTX_SUFF(pfnWriteCallback) || !pRange->pfnWriteCallbackR3);
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * Get data to write from second parameter,
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync * and call the callback to write it.
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync unsigned cb = 0;
212ccded142c57ca5b0ce90d5b116d2e5e4c0195vboxsync bool fRc = iomGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &u64Data, &cb);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync int rc = iomMMIODoWrite(pVM, pRange, GCPhysFault, &u64Data, cb);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync/** Wrapper for reading virtual memory. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsyncDECLINLINE(int) iomRamRead(PVM pVM, void *pDest, RTGCPTR GCSrc, uint32_t cb)
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync return MMGCRamReadNoTrapHandler(pDest, (void *)GCSrc, cb);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync/** Wrapper for writing virtual memory. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsyncDECLINLINE(int) iomRamWrite(PVM pVM, RTGCPTR GCDest, void *pSrc, uint32_t cb)
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync return MMGCRamWriteNoTrapHandler((void *)GCDest, pSrc, cb);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * [REP] MOVSB
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * [REP] MOVSW
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * [REP] MOVSD
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Restricted implementation.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * @returns VBox status code.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * @param pVM The virtual machine.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * @param uErrorCode CPU Error code.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * @param pRegFrame Trap register frame.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * @param GCPhysFault The GC physical address corresponding to pvFault.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * @param pCpu Disassembler CPU state.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * @param pRange Pointer MMIO range.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * @param ppStat Which sub-sample to attribute this call to.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsyncstatic int iomInterpretMOVS(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, PSTAMPROFILE *ppStat)
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * We do not support segment prefixes or REPNE.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync return VINF_IOM_HC_MMIO_READ_WRITE; /** @todo -> interpret whatever. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync if (SELMGetCpuModeFromSelector(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid) == CPUMODE_16BIT)
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync /* Get the current privilege level. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Get data size.
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync unsigned cb = DISGetParamSize(pCpu, &pCpu->param1);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync AssertMsg(cb > 0 && cb <= sizeof(uint32_t), ("cb=%d\n", cb));
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync int offIncrement = pRegFrame->eflags.Bits.u1DF ? -(signed)cb : (signed)cb;
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync if (pVM->iom.s.cMovsMaxBytes < (cTransfers << SIZE_2_SHIFT(cb)))
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync pVM->iom.s.cMovsMaxBytes = cTransfers << SIZE_2_SHIFT(cb);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync/** @todo re-evaluate on page boundraries. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Write operation: [Mem] -> [MMIO]
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * ds:esi (Virt Src) -> es:edi (Phys Dst)
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync STAM_STATS({ *ppStat = &pVM->iom.s.StatRZInstMovsToMMIO; });
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync /* Check callback. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync /* Convert source address ds:esi. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync rc = SELMToFlatEx(pVM, DIS_SELREG_DS, pRegFrame, (RTGCPTR)pRegFrame->rsi,
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync /* Access verification first; we currently can't recover properly from traps inside this instruction */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync rc = PGMVerifyAccess(pVM, pu8Virt, cTransfers * cb, (cpl == 3) ? X86_PTE_US : 0);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync Log(("MOVS will generate a trap -> recompiler, rc=%d\n", rc));
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync /* copy loop. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync rc = iomRamRead(pVM, &u32Data, (RTGCPTR)pu8Virt, cb);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync rc = iomMMIODoWrite(pVM, pRange, Phys, &u32Data, cb);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync /* Update ecx. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Read operation: [MMIO] -> [mem] or [MMIO] -> [MMIO]
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * ds:[eSI] (Phys Src) -> es:[eDI] (Virt Dst)
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync STAM_STATS({ *ppStat = &pVM->iom.s.StatRZInstMovsFromMMIO; });
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync /* Check callback. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync /* Convert destination address. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync rc = SELMToFlatEx(pVM, DIS_SELREG_ES, pRegFrame, (RTGCPTR)pRegFrame->rdi,
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync /* Check if destination address is MMIO. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync rc = PGMGstGetPage(pVM, (RTGCPTR)pu8Virt, NULL, &PhysDst);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync PhysDst |= (RTGCUINTPTR)pu8Virt & PAGE_OFFSET_MASK;
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync && (pMMIODst = iomMMIOGetRange(&pVM->iom.s, PhysDst)))
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync * Extra: [MMIO] -> [MMIO]
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync STAM_STATS({ *ppStat = &pVM->iom.s.StatRZInstMovsMMIO; });
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync if (!pMMIODst->CTX_SUFF(pfnWriteCallback) && pMMIODst->pfnWriteCallbackR3)
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync /* copy loop. */
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync rc = iomMMIODoRead(pVM, pRange, Phys, &u32Data, cb);
db453c26f429ba8057ea92644ddd59279b9a918dvboxsync rc = iomMMIODoWrite(pVM, pMMIODst, PhysDst, &u32Data, cb);
cTransfers--;
/* Access verification first; we currently can't recover properly from traps inside this instruction */
return VINF_EM_RAW_EMULATE_INSTR;
#ifdef IN_GC
while (cTransfers)
cTransfers--;
#ifdef IN_GC
return rc;
static int iomInterpretSTOS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
#ifndef IN_GC
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 (offIncrement > 0)
rc = pRange->CTX_SUFF(pfnFillCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), Phys, u32Data, cb, cTransfers);
rc = pRange->CTX_SUFF(pfnFillCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), (Phys - (cTransfers - 1)) << SIZE_2_SHIFT(cb), u32Data, cb, cTransfers);
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;
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;
fAndWrite = false;
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;
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 cb = 0;
int rc;
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;
return rc;
VMMDECL(int) IOMMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)
#ifdef VBOX_WITH_STATISTICS
if (!pStats)
# ifdef IN_RING3
return VERR_NO_MEMORY;
#ifndef IN_RING3
# ifdef VBOX_WITH_STATISTICS
unsigned cbOp;
case OP_MOV:
case OP_MOVZX:
case OP_MOVSX:
#ifdef IOM_WITH_MOVS_SUPPORT
case OP_MOVSB:
case OP_MOVSWD:
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;
#ifdef IN_RING3
DECLCALLBACK(int) IOMR3MMIOHandler(PVM pVM, RTGCPHYS GCPhysFault, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
int rc;
return rc;
("Handlers and page tables are out of sync or something! GCPhys=%VGp cbValue=%d\n", GCPhys, cbValue),
#ifdef VBOX_WITH_STATISTICS
if (!pStats)
# ifdef IN_RING3
return VERR_NO_MEMORY;
return VINF_IOM_HC_MMIO_READ;
#ifdef VBOX_WITH_STATISTICS
int rc = pRange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhys, pu32Value, cbValue);
#ifdef VBOX_WITH_STATISTICS
switch (rc)
case VINF_SUCCESS:
return rc;
case VINF_IOM_MMIO_UNUSED_00:
switch (cbValue)
return VINF_SUCCESS;
case VINF_IOM_MMIO_UNUSED_FF:
switch (cbValue)
return VINF_SUCCESS;
#ifndef IN_RING3
return VINF_IOM_HC_MMIO_READ;
#ifdef VBOX_WITH_STATISTICS
switch (cbValue)
Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=VINF_SUCCESS\n", GCPhys, *pu32Value, cbValue));
return VINF_SUCCESS;
("Handlers and page tables are out of sync or something! GCPhys=%VGp cbValue=%d\n", GCPhys, cbValue),
#ifdef VBOX_WITH_STATISTICS
if (!pStats)
# ifdef IN_RING3
return VERR_NO_MEMORY;
return VINF_IOM_HC_MMIO_WRITE;
#ifdef VBOX_WITH_STATISTICS
int rc = pRange->CTX_SUFF(pfnWriteCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhys, &u32Value, cbValue);
#ifdef VBOX_WITH_STATISTICS
return rc;
#ifndef IN_RING3
return VINF_IOM_HC_MMIO_WRITE;
#ifdef VBOX_WITH_STATISTICS
Log4(("IOMMMIOWrite: GCPhys=%RGp u32=%08RX32 cb=%d rc=%Vrc\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(int) IOMInterpretINSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, uint32_t cbTransfer)
#ifdef VBOX_WITH_STATISTICS
return VINF_EM_RAW_EMULATE_INSTR;
#ifndef IN_GC
return VINF_EM_RAW_EMULATE_INSTR;
if (SELMGetCpuModeFromSelector(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid) == CPUMODE_16BIT)
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_GC
cTransfers--;
#ifdef IN_GC
AssertMsg(rc == VINF_SUCCESS || rc == VINF_IOM_HC_IOPORT_READ || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST) || RT_FAILURE(rc), ("%Vrc\n", rc));
return rc;
* @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(rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_TRPM_XCPT_DISPATCHED || rc == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rc), ("%Vrc\n", rc));
return rc;
* @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(int) IOMInterpretOUTSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, uint32_t cbTransfer)
#ifdef VBOX_WITH_STATISTICS
return VINF_EM_RAW_EMULATE_INSTR;
#ifndef IN_GC
return VINF_EM_RAW_EMULATE_INSTR;
if (SELMGetCpuModeFromSelector(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid) == CPUMODE_16BIT)
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_GC
cTransfers--;
#ifdef IN_GC
AssertMsg(rc == VINF_SUCCESS || rc == VINF_IOM_HC_IOPORT_WRITE || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST) || RT_FAILURE(rc), ("%Vrc\n", rc));
return rc;
* @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(rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_TRPM_XCPT_DISPATCHED || rc == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rc), ("%Vrc\n", rc));
return rc;
#ifndef IN_GC
* Modify an existing MMIO region page; map to another guest physical region and change the access flags
VMMDECL(int) IOMMMIOModifyPage(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysRemapped, uint64_t fPageFlags)
return VINF_SUCCESS;
unsigned cb;
while(cb)
return VINF_SUCCESS;