IOMAllMMIO.cpp revision dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1
2N/A * available from http://www.virtualbox.org. This file is free software;
2N/A#include "IOMInternal.h"
2N/Astatic bool iomGetRegImmData(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam, PCPUMCTXCORE pRegFrame, uint32_t *pu32Data, unsigned *pcbSize);
2N/Astatic bool iomSaveDataToReg(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam, PCPUMCTXCORE pRegFrame, uint32_t u32Data);
2N/Astatic unsigned g_aReg32Index[] =
2N/Astatic unsigned g_aReg16Index[] =
2N/Astatic unsigned g_aReg8Index[] =
2N/Astatic unsigned g_aRegSegIndex[] =
2N/Astatic const unsigned g_aSize2Shift[] =
2N/ADECLINLINE(int) iomMMIODoWrite(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, const void *pvData, unsigned cb)
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A rc = pRange->CTXALLSUFF(pfnWriteCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhysFault, (void *)pvData, cb); /* @todo fix const!! */
2N/ADECLINLINE(int) iomMMIODoRead(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, void *pvData, unsigned cb)
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A rc = pRange->CTXALLSUFF(pfnReadCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhysFault, pvData, cb);
2N/Astatic bool iomGetRegImmData(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam, PCPUMCTXCORE pRegFrame, uint32_t *pu32Data, unsigned *pcbSize)
2N/A if (pParam->flags & (USE_BASE | USE_INDEX | USE_SCALE | USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32))
2N/Astatic bool iomSaveDataToReg(PDISCPUSTATE pCpu, PCOP_PARAMETER pParam, PCPUMCTXCORE pRegFrame, unsigned u32Data)
2N/A if (pParam->flags & (USE_BASE | USE_INDEX | USE_SCALE | USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_IMMEDIATE8 | USE_IMMEDIATE16 | USE_IMMEDIATE32 | USE_IMMEDIATE32_SX8 | USE_IMMEDIATE16_SX8))
2N/A#ifdef VBOX_WITH_STATISTICS
2N/Astatic int iomInterpretMOVxXRead(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
2N/Astatic int iomInterpretMOVxXWrite(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
2N/A#ifdef iom_MOVS_SUPPORT
2N/Astatic int iomInterpretMOVS(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
2N/A if (!cTransfers)
2N/A return VINF_SUCCESS;
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A return VINF_IOM_HC_MMIO_WRITE;
2N/A rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->ds, (RTGCPTR)pRegFrame->esi, &pRegFrame->dsHid,
2N/A /* Access verification first; we currently can't recover properly from traps inside this instruction */
2N/A return VINF_EM_RAW_EMULATE_INSTR;
2N/A while (cTransfers)
2N/A cTransfers--;
2N/A return VINF_IOM_HC_MMIO_READ;
2N/A rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->es, (RTGCPTR)pRegFrame->edi, &pRegFrame->esHid,
2N/A return VINF_EM_RAW_GUEST_TRAP;
2N/A return VINF_IOM_HC_MMIO_READ_WRITE;
2N/A while (cTransfers)
2N/A cTransfers--;
2N/A /* Access verification first; we currently can't recover properly from traps inside this instruction */
2N/A rc = PGMVerifyAccess(pVM, pu8Virt, cTransfers * cb, X86_PTE_RW | ((cpl == 3) ? X86_PTE_US : 0));
2N/A return VINF_EM_RAW_EMULATE_INSTR;
2N/A while (cTransfers)
2N/A cTransfers--;
2N/Astatic int iomInterpretSTOS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
2N/A if (!cTransfers)
2N/A return VINF_SUCCESS;
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A if (offIncrement > 0)
2N/A rc = pRange->CTXALLSUFF(pfnFillCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), Phys, u32Data, cb, cTransfers);
2N/A rc = pRange->CTXALLSUFF(pfnFillCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), (Phys - (cTransfers - 1)) << SIZE_2_SHIFT(cb), u32Data, cb, cTransfers);
2N/A cTransfers--;
2N/A } while (cTransfers);
2N/Astatic int iomInterpretLODS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
2N/Astatic int iomInterpretCMP(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
2N/A pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
2N/Astatic int iomInterpretAND(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
2N/A pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
2N/Astatic int iomInterpretTEST(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
2N/A pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
2N/Astatic int iomInterpretXCHG(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
2N/A return VINF_IOM_HC_MMIO_READ_WRITE;
2N/AIOMDECL(int) IOMMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser)
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A return VERR_NO_MEMORY;
2N/A# ifdef VBOX_WITH_STATISTICS
2N/A#ifdef iom_MOVS_SUPPORT
2N/A case VINF_IOM_HC_MMIO_READ:
2N/A case VINF_IOM_HC_MMIO_WRITE:
2N/A ("Handlers and page tables are out of sync or something! GCPhys=%VGp cbValue=%d\n", GCPhys, cbValue),
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A return VERR_NO_MEMORY;
2N/A return VINF_IOM_HC_MMIO_READ;
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A int rc = pRange->CTXALLSUFF(pfnReadCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhys, pu32Value, cbValue);
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A case VINF_SUCCESS:
2N/A Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=%Vrc\n", GCPhys, *pu32Value, cbValue, rc));
2N/A case VINF_IOM_MMIO_UNUSED_00:
2N/A Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=%Vrc\n", GCPhys, *pu32Value, cbValue, rc));
2N/A return VINF_SUCCESS;
2N/A case VINF_IOM_MMIO_UNUSED_FF:
2N/A Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=%Vrc\n", GCPhys, *pu32Value, cbValue, rc));
2N/A return VINF_SUCCESS;
2N/A return VINF_IOM_HC_MMIO_READ;
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=VINF_SUCCESS\n", GCPhys, *pu32Value, cbValue));
2N/A return VINF_SUCCESS;
2N/A ("Handlers and page tables are out of sync or something! GCPhys=%VGp cbValue=%d\n", GCPhys, cbValue),
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A return VERR_NO_MEMORY;
2N/A return VINF_IOM_HC_MMIO_WRITE;
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A int rc = pRange->CTXALLSUFF(pfnWriteCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhys, &u32Value, cbValue);
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A Log4(("IOMMMIOWrite: GCPhys=%RGp u32=%08RX32 cb=%d rc=%Vrc\n", GCPhys, u32Value, cbValue, rc));
2N/A return VINF_IOM_HC_MMIO_WRITE;
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A Log4(("IOMMMIOWrite: GCPhys=%RGp u32=%08RX32 cb=%d rc=%Vrc\n", GCPhys, u32Value, cbValue, VINF_SUCCESS));
2N/A return VINF_SUCCESS;
2N/A * @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
2N/A * @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
2N/AIOMDECL(int) IOMInterpretINSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, uint32_t cbTransfer)
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A return VINF_EM_RAW_EMULATE_INSTR;
2N/A if (!cTransfers)
2N/A return VINF_SUCCESS;
2N/A int rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->es, (RTGCPTR)pRegFrame->edi, &pRegFrame->esHid,
2N/A return VINF_EM_RAW_EMULATE_INSTR;
2N/A /* Access verification first; we can't recover from traps inside this instruction, as the port read cannot be repeated. */
2N/A return VINF_EM_RAW_EMULATE_INSTR;
2N/A cTransfers--;
2N/A AssertMsg(rc == VINF_SUCCESS || rc == VINF_IOM_HC_IOPORT_READ || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST) || VBOX_FAILURE(rc), ("%Vrc\n", rc));
2N/A * @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
2N/A * @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
2N/A AssertMsg(rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_TRPM_XCPT_DISPATCHED || rc == VINF_TRPM_XCPT_DISPATCHED || VBOX_FAILURE(rc), ("%Vrc\n", rc));
2N/A * @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
2N/A * @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
2N/AIOMDECL(int) IOMInterpretOUTSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, uint32_t cbTransfer)
2N/A#ifdef VBOX_WITH_STATISTICS
2N/A return VINF_EM_RAW_EMULATE_INSTR;
2N/A if (!cTransfers)
2N/A return VINF_SUCCESS;
2N/A int rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->ds, (RTGCPTR)pRegFrame->esi, &pRegFrame->dsHid,
2N/A return VINF_EM_RAW_EMULATE_INSTR;
2N/A /* Access verification first; we currently can't recover properly from traps inside this instruction */
2N/A return VINF_EM_RAW_EMULATE_INSTR;
2N/A cTransfers--;
2N/A AssertMsg(rc == VINF_SUCCESS || rc == VINF_IOM_HC_IOPORT_WRITE || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST) || VBOX_FAILURE(rc), ("%Vrc\n", rc));
2N/A * @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)
2N/A * @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)
2N/A AssertMsg(rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_TRPM_XCPT_DISPATCHED || rc == VINF_TRPM_XCPT_DISPATCHED || VBOX_FAILURE(rc), ("%Vrc\n", rc));