MMRamRC.cpp revision 683371bbf37760161d1b8454ce978acf89bbb04f
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/* $Id$ */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/** @file
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * MMRamGC - Guest Context Ram access Routines, pair for MMRamGCA.asm.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*
77bbd3327e8130eb01de6c1c1d1ef54e0ab48be8vboxsync * Copyright (C) 2006-2007 Oracle Corporation
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * available from http://www.virtualbox.org. This file is free software;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * you can redistribute it and/or modify it under the terms of the GNU
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * General Public License (GPL) as published by the Free Software
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*******************************************************************************
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync* Header Files *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync*******************************************************************************/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#define LOG_GROUP LOG_GROUP_MM
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/vmm/mm.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/vmm/cpum.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/vmm/trpm.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/vmm/em.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include "MMInternal.h"
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/vmm/vm.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/vmm/vmm.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/vmm/pgm.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <iprt/assert.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/param.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/err.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*******************************************************************************
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync* Internal Functions *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync*******************************************************************************/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic DECLCALLBACK(int) mmGCRamTrap0eHandler(PVM pVM, PCPUMCTXCORE pRegFrame);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncDECLASM(void) MMGCRamReadNoTrapHandler_EndProc(void);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncDECLASM(void) MMGCRamWriteNoTrapHandler_EndProc(void);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncDECLASM(void) MMGCRamRead_Error(void);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncDECLASM(void) MMGCRamWrite_Error(void);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync/**
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Install MMGCRam Hypervisor page fault handler for normal working
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * of MMGCRamRead and MMGCRamWrite calls.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * This handler will be automatically removed at page fault.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * In other case it must be removed by MMGCRamDeregisterTrapHandler call.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync *
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync * @param pVM VM handle.
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync */
6febf3149010855617e4a37e2c49f93d68930d44vboxsyncVMMRCDECL(void) MMGCRamRegisterTrapHandler(PVM pVM)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync{
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync TRPMGCSetTempHandler(pVM, 0xe, mmGCRamTrap0eHandler);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync}
80e46f984efd827517661c0e081a36014ca41af8vboxsync
80e46f984efd827517661c0e081a36014ca41af8vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync/**
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Remove MMGCRam Hypervisor page fault handler.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * See description of MMGCRamRegisterTrapHandler call.
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync *
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pVM VM handle.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMRCDECL(void) MMGCRamDeregisterTrapHandler(PVM pVM)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync{
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync TRPMGCSetTempHandler(pVM, 0xe, NULL);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/**
710a6316a22868b04400caf79719f96c18163cd3vboxsync * Read data in guest context with #PF control.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync *
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @returns VBox status.
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * @param pVM The VM handle.
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync * @param pDst Where to store the read data.
06782e19f5e2144408396dcec922c423c5ef9da8vboxsync * @param pSrc Pointer to the data to read.
80e46f984efd827517661c0e081a36014ca41af8vboxsync * @param cb Size of data to read, only 1/2/4/8 is valid.
80e46f984efd827517661c0e081a36014ca41af8vboxsync */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMRCDECL(int) MMGCRamRead(PVM pVM, void *pDst, void *pSrc, size_t cb)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync int rc;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync PVMCPU pVCpu = VMMGetCpu0(pVM);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync TRPMSaveTrap(pVCpu); /* save the current trap info, because it will get trashed if our access failed. */
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync MMGCRamRegisterTrapHandler(pVM);
6febf3149010855617e4a37e2c49f93d68930d44vboxsync rc = MMGCRamReadNoTrapHandler(pDst, pSrc, cb);
63b785c3291332a86a9bc473e68f08121368898bvboxsync MMGCRamDeregisterTrapHandler(pVM);
80e46f984efd827517661c0e081a36014ca41af8vboxsync if (RT_FAILURE(rc))
80e46f984efd827517661c0e081a36014ca41af8vboxsync TRPMRestoreTrap(pVCpu);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return rc;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync}
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync/**
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Write data in guest context with #PF control.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync *
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @returns VBox status.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pVM The VM handle.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pDst Where to write the data.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pSrc Pointer to the data to write.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param cb Size of data to write, only 1/2/4 is valid.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @deprecated Don't use this as it doesn't check the page state.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync */
fb1975a6972d89de9e515bed0248db93f04ec9d8vboxsyncVMMRCDECL(int) MMGCRamWrite(PVM pVM, void *pDst, void *pSrc, size_t cb)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync PVMCPU pVCpu = VMMGetCpu0(pVM);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync TRPMSaveTrap(pVCpu); /* save the current trap info, because it will get trashed if our access failed. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync MMGCRamRegisterTrapHandler(pVM);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync int rc = MMGCRamWriteNoTrapHandler(pDst, pSrc, cb);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync MMGCRamDeregisterTrapHandler(pVM);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (RT_FAILURE(rc))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync TRPMRestoreTrap(pVCpu);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /*
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * And mark the relevant guest page as accessed and dirty.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync PGMGstModifyPage(VMMGetCpu0(pVM), (RTGCPTR)(RTRCUINTPTR)pDst, cb, X86_PTE_A | X86_PTE_D, ~(uint64_t)(X86_PTE_A | X86_PTE_D));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync return rc;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync/**
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * \#PF Handler for servicing traps inside MMGCRamReadNoTrapHandler and MMGCRamWriteNoTrapHandler functions.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync *
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @internal
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncDECLCALLBACK(int) mmGCRamTrap0eHandler(PVM pVM, PCPUMCTXCORE pRegFrame)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /*
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Page fault inside MMGCRamRead()? Resume at *_Error.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if ( (uintptr_t)&MMGCRamReadNoTrapHandler < (uintptr_t)pRegFrame->eip
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync && (uintptr_t)pRegFrame->eip < (uintptr_t)&MMGCRamReadNoTrapHandler_EndProc)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Must be a read violation. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync AssertReturn(!(TRPMGetErrorCode(VMMGetCpu0(pVM)) & X86_TRAP_PF_RW), VERR_MM_BAD_TRAP_TYPE_IPE);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pRegFrame->eip = (uintptr_t)&MMGCRamRead_Error;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return VINF_SUCCESS;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /*
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Page fault inside MMGCRamWrite()? Resume at _Error.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync if ( (uintptr_t)&MMGCRamWriteNoTrapHandler < (uintptr_t)pRegFrame->eip
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync && (uintptr_t)pRegFrame->eip < (uintptr_t)&MMGCRamWriteNoTrapHandler_EndProc)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync {
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Must be a write violation. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync AssertReturn(TRPMGetErrorCode(VMMGetCpu0(pVM)) & X86_TRAP_PF_RW, VERR_MM_BAD_TRAP_TYPE_IPE);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pRegFrame->eip = (uintptr_t)&MMGCRamWrite_Error;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return VINF_SUCCESS;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /*
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * #PF is not handled - cause guru meditation.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return VERR_INTERNAL_ERROR;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync