IOMAllMMIO.cpp revision f5395a2af3050ddd694b0ad505975f7b717ab4f1
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * IOM - Input / Output Monitor - Guest Context.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * available from http://www.virtualbox.org. This file is free software;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * you can redistribute it and/or modify it under the terms of the GNU
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * General Public License (GPL) as published by the Free Software
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * additional information or have any questions.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/*******************************************************************************
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync* Header Files *
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync*******************************************************************************/
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/*******************************************************************************
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync* Global Variables *
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync*******************************************************************************/
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Array for fast recode of the operand size (1/2/4/8 bytes) to bit shift value.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncstatic const unsigned g_aSize2Shift[] =
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ~0, /* 0 - invalid */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync 0, /* *1 == 2^0 */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ~0, /* 3 - invalid */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ~0, /* 5 - invalid */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ~0, /* 6 - invalid */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ~0, /* 7 - invalid */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Macro for fast recode of the operand size (1/2/4/8 bytes) to bit shift value.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Wrapper which does the write and updates range statistics when such are enabled.
DECLINLINE(int) iomMMIODoWrite(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, const void *pvData, unsigned cb)
#ifdef VBOX_WITH_STATISTICS
int rc;
rc = pRange->CTXALLSUFF(pfnWriteCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhysFault, (void *)pvData, cb); /* @todo fix const!! */
return rc;
DECLINLINE(int) iomMMIODoRead(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, void *pvData, unsigned cb)
#ifdef VBOX_WITH_STATISTICS
int rc;
rc = pRange->CTXALLSUFF(pfnReadCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhysFault, pvData, cb);
switch (cb)
return rc;
#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_GC
#ifdef IN_GC
#ifdef iom_MOVS_SUPPORT
static int iomInterpretMOVS(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
if (SELMGetCpuModeFromSelector(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid) == CPUMODE_16BIT)
if (!cTransfers)
return VINF_SUCCESS;
#ifdef VBOX_WITH_STATISTICS
int rc;
return VINF_IOM_HC_MMIO_WRITE;
rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->ds, (RTGCPTR)pRegFrame->esi, &pRegFrame->dsHid,
/* 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 VINF_IOM_HC_MMIO_READ;
rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->es, (RTGCPTR)pRegFrame->edi, &pRegFrame->esHid,
return VINF_EM_RAW_GUEST_TRAP;
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_GC
while (cTransfers)
cTransfers--;
#ifdef IN_GC
return rc;
static int iomInterpretSTOS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
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->CTXALLSUFF(pfnFillCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), Phys, u32Data, cb, cTransfers);
rc = pRange->CTXALLSUFF(pfnFillCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(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 iomInterpretAND(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
unsigned cb = 0;
bool fAndWrite;
int rc;
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 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;
IOMDECL(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_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_TEST:
case OP_XCHG:
switch (rc)
case VINF_IOM_HC_MMIO_READ:
case VINF_IOM_HC_MMIO_WRITE:
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
if (pStats)
int rc = pRange->CTXALLSUFF(pfnReadCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhys, pu32Value, cbValue);
#ifdef VBOX_WITH_STATISTICS
if (pStats)
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
if (pStats)
*pu32Value = 0;
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
if (pStats)
int rc = pRange->CTXALLSUFF(pfnWriteCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhys, &u32Value, cbValue);
#ifdef VBOX_WITH_STATISTICS
if (pStats)
return rc;
#ifndef IN_RING3
return VINF_IOM_HC_MMIO_WRITE;
#ifdef VBOX_WITH_STATISTICS
if (pStats)
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)
IOMDECL(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;
if (SELMGetCpuModeFromSelector(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid) == CPUMODE_16BIT)
if (!cTransfers)
return VINF_SUCCESS;
int rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->es, (RTGCPTR)pRegFrame->edi, &pRegFrame->esHid,
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) || VBOX_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 || VBOX_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)
IOMDECL(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;
if (SELMGetCpuModeFromSelector(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid) == CPUMODE_16BIT)
if (!cTransfers)
return VINF_SUCCESS;
int rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->ds, (RTGCPTR)pRegFrame->esi, &pRegFrame->dsHid,
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) || VBOX_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 || VBOX_FAILURE(rc), ("%Vrc\n", rc));
return rc;