IOMAllMMIO.cpp revision 021a33be84282e41b811563b5f60f3ada196af3e
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * IOM - Input / Output Monitor - Any Context, MMIO & String I/O.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * Copyright (C) 2006-2010 Oracle Corporation
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * available from http://www.virtualbox.org. This file is free software;
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * you can redistribute it and/or modify it under the terms of the GNU
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * General Public License (GPL) as published by the Free Software
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync/*******************************************************************************
f78b12e570284aa8291f4ca1add24937fd107403vboxsync* Header Files *
f78b12e570284aa8291f4ca1add24937fd107403vboxsync*******************************************************************************/
f78b12e570284aa8291f4ca1add24937fd107403vboxsync#if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3)
f78b12e570284aa8291f4ca1add24937fd107403vboxsync/*******************************************************************************
f78b12e570284aa8291f4ca1add24937fd107403vboxsync* Global Variables *
f78b12e570284aa8291f4ca1add24937fd107403vboxsync*******************************************************************************/
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * Array for fast recode of the operand size (1/2/4/8 bytes) to bit shift value.
f78b12e570284aa8291f4ca1add24937fd107403vboxsyncstatic const unsigned g_aSize2Shift[] =
f78b12e570284aa8291f4ca1add24937fd107403vboxsync ~0, /* 0 - invalid */
f78b12e570284aa8291f4ca1add24937fd107403vboxsync 0, /* *1 == 2^0 */
f78b12e570284aa8291f4ca1add24937fd107403vboxsync ~0, /* 3 - invalid */
f78b12e570284aa8291f4ca1add24937fd107403vboxsync ~0, /* 5 - invalid */
f78b12e570284aa8291f4ca1add24937fd107403vboxsync ~0, /* 6 - invalid */
f78b12e570284aa8291f4ca1add24937fd107403vboxsync ~0, /* 7 - invalid */
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * Macro for fast recode of the operand size (1/2/4/8 bytes) to bit shift value.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * Wrapper which does the write and updates range statistics when such are enabled.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @warning RT_SUCCESS(rc=VINF_IOM_HC_MMIO_WRITE) is TRUE!
f78b12e570284aa8291f4ca1add24937fd107403vboxsyncstatic int iomMMIODoWrite(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, const void *pvData, unsigned cb)
f78b12e570284aa8291f4ca1add24937fd107403vboxsync PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, GCPhysFault, pRange);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfWrite), a);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync rc = pRange->CTX_SUFF(pfnWriteCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser),
f78b12e570284aa8291f4ca1add24937fd107403vboxsync GCPhysFault, (void *)pvData, cb); /** @todo fix const!! */
f78b12e570284aa8291f4ca1add24937fd107403vboxsync STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfWrite), a);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * Wrapper which does the read and updates range statistics when such are enabled.
f78b12e570284aa8291f4ca1add24937fd107403vboxsyncDECLINLINE(int) iomMMIODoRead(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhys, void *pvValue, unsigned cbValue)
f78b12e570284aa8291f4ca1add24937fd107403vboxsync PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, GCPhys, pRange);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfRead), a);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync rc = pRange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhys, pvValue, cbValue);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync case 1: *(uint8_t *)pvValue = UINT8_C(0xff); break;
f78b12e570284aa8291f4ca1add24937fd107403vboxsync case 2: *(uint16_t *)pvValue = UINT16_C(0xffff); break;
f78b12e570284aa8291f4ca1add24937fd107403vboxsync case 4: *(uint32_t *)pvValue = UINT32_C(0xffffffff); break;
f78b12e570284aa8291f4ca1add24937fd107403vboxsync case 8: *(uint64_t *)pvValue = UINT64_C(0xffffffffffffffff); break;
f78b12e570284aa8291f4ca1add24937fd107403vboxsync default: AssertReleaseMsgFailed(("cbValue=%d GCPhys=%RGp\n", cbValue, GCPhys)); break;
f78b12e570284aa8291f4ca1add24937fd107403vboxsync case 1: *(uint8_t *)pvValue = UINT8_C(0x00); break;
f78b12e570284aa8291f4ca1add24937fd107403vboxsync case 2: *(uint16_t *)pvValue = UINT16_C(0x0000); break;
f78b12e570284aa8291f4ca1add24937fd107403vboxsync case 4: *(uint32_t *)pvValue = UINT32_C(0x00000000); break;
f78b12e570284aa8291f4ca1add24937fd107403vboxsync case 8: *(uint64_t *)pvValue = UINT64_C(0x0000000000000000); break;
f78b12e570284aa8291f4ca1add24937fd107403vboxsync default: AssertReleaseMsgFailed(("cbValue=%d GCPhys=%RGp\n", cbValue, GCPhys)); break;
f78b12e570284aa8291f4ca1add24937fd107403vboxsync STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfRead), a);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * Internal - statistics only.
f78b12e570284aa8291f4ca1add24937fd107403vboxsyncDECLINLINE(void) iomMMIOStatLength(PVM pVM, unsigned cb)
f78b12e570284aa8291f4ca1add24937fd107403vboxsync /* No way. */
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * MOV reg, mem (read)
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * MOVZX reg, mem (read)
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * MOVSX reg, mem (read)
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @returns VBox status code.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @param pVM The virtual machine.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @param pCpu Disassembler CPU state.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @param pRange Pointer MMIO range.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @param GCPhysFault The GC physical address corresponding to pvFault.
f78b12e570284aa8291f4ca1add24937fd107403vboxsyncstatic int iomInterpretMOVxXRead(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
f78b12e570284aa8291f4ca1add24937fd107403vboxsync Assert(pRange->CTX_SUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * Get the data size from parameter 2,
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * and call the handler function to get the data.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync unsigned cb = DISGetParamSize(pCpu, &pCpu->param2);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync AssertMsg(cb > 0 && cb <= sizeof(uint64_t), ("cb=%d\n", cb));
f78b12e570284aa8291f4ca1add24937fd107403vboxsync int rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &u64Data, cb);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * Do sign extension for MOVSX.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync /** @todo checkup MOVSX implementation! */
f78b12e570284aa8291f4ca1add24937fd107403vboxsync /* DWORD <- BYTE */
f78b12e570284aa8291f4ca1add24937fd107403vboxsync /* DWORD <- WORD */
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * Store the result to register (parameter 1).
f78b12e570284aa8291f4ca1add24937fd107403vboxsync bool fRc = iomSaveDataToReg(pCpu, &pCpu->param1, pRegFrame, u64Data);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync AssertMsg(fRc, ("Failed to store register value!\n")); NOREF(fRc);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * MOV mem, reg|imm (write)
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @returns VBox status code.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @param pVM The virtual machine.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @param pCpu Disassembler CPU state.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @param pRange Pointer MMIO range.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * @param GCPhysFault The GC physical address corresponding to pvFault.
f78b12e570284aa8291f4ca1add24937fd107403vboxsyncstatic int iomInterpretMOVxXWrite(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
f78b12e570284aa8291f4ca1add24937fd107403vboxsync Assert(pRange->CTX_SUFF(pfnWriteCallback) || !pRange->pfnWriteCallbackR3);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * Get data to write from second parameter,
f78b12e570284aa8291f4ca1add24937fd107403vboxsync * and call the callback to write it.
f78b12e570284aa8291f4ca1add24937fd107403vboxsync unsigned cb = 0;
f78b12e570284aa8291f4ca1add24937fd107403vboxsync bool fRc = iomGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &u64Data, &cb);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync int rc = iomMMIODoWrite(pVM, pRange, GCPhysFault, &u64Data, cb);
f78b12e570284aa8291f4ca1add24937fd107403vboxsync/** Wrapper for reading virtual memory. */
#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*/);
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;
static int iomInterpretSTOS(PVM pVM, 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 (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;
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;
if (!pLock)
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,
if (!pLock)
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;
if (!pLock)
return rc;
rc = pRange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhys, pu32Value, (unsigned)cbValue);
switch (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:
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;
switch (cbValue)
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;
if (!pLock)
return rc;
#ifndef IN_RING3
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, uint32_t cbTransfer)
return VINF_EM_RAW_EMULATE_INSTR;
#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;
&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, uint32_t cbTransfer)
return VINF_EM_RAW_EMULATE_INSTR;
#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;
&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;