VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMGC/MMRamGC.cpp@ 29561

Last change on this file since 29561 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.5 KB
Line 
1/* $Id: MMRamGC.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
2/** @file
3 * MMRamGC - Guest Context Ram access Routines, pair for MMRamGCA.asm.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_MM
23#include <VBox/mm.h>
24#include <VBox/cpum.h>
25#include <VBox/trpm.h>
26#include <VBox/em.h>
27#include "MMInternal.h"
28#include <VBox/vm.h>
29#include <VBox/vmm.h>
30#include <VBox/pgm.h>
31
32#include <iprt/assert.h>
33#include <VBox/param.h>
34#include <VBox/err.h>
35
36
37/*******************************************************************************
38* Internal Functions *
39*******************************************************************************/
40static DECLCALLBACK(int) mmGCRamTrap0eHandler(PVM pVM, PCPUMCTXCORE pRegFrame);
41
42DECLASM(void) MMGCRamReadNoTrapHandler_EndProc(void);
43DECLASM(void) MMGCRamWriteNoTrapHandler_EndProc(void);
44DECLASM(void) EMGCEmulateLockCmpXchg_EndProc(void);
45DECLASM(void) EMGCEmulateLockCmpXchg_Error(void);
46DECLASM(void) EMGCEmulateCmpXchg_EndProc(void);
47DECLASM(void) EMGCEmulateCmpXchg_Error(void);
48DECLASM(void) EMGCEmulateLockCmpXchg8b_EndProc(void);
49DECLASM(void) EMGCEmulateLockCmpXchg8b_Error(void);
50DECLASM(void) EMGCEmulateCmpXchg8b_EndProc(void);
51DECLASM(void) EMGCEmulateCmpXchg8b_Error(void);
52DECLASM(void) EMGCEmulateLockXAdd_EndProc(void);
53DECLASM(void) EMGCEmulateLockXAdd_Error(void);
54DECLASM(void) EMGCEmulateXAdd_EndProc(void);
55DECLASM(void) EMGCEmulateXAdd_Error(void);
56DECLASM(void) EMEmulateLockOr_EndProc(void);
57DECLASM(void) EMEmulateLockOr_Error(void);
58DECLASM(void) EMEmulateLockBtr_EndProc(void);
59DECLASM(void) EMEmulateLockBtr_Error(void);
60DECLASM(void) MMGCRamRead_Error(void);
61DECLASM(void) MMGCRamWrite_Error(void);
62
63
64/**
65 * Install MMGCRam Hypervisor page fault handler for normal working
66 * of MMGCRamRead and MMGCRamWrite calls.
67 * This handler will be automatically removed at page fault.
68 * In other case it must be removed by MMGCRamDeregisterTrapHandler call.
69 *
70 * @param pVM VM handle.
71 */
72VMMRCDECL(void) MMGCRamRegisterTrapHandler(PVM pVM)
73{
74 TRPMGCSetTempHandler(pVM, 0xe, mmGCRamTrap0eHandler);
75}
76
77
78/**
79 * Remove MMGCRam Hypervisor page fault handler.
80 * See description of MMGCRamRegisterTrapHandler call.
81 *
82 * @param pVM VM handle.
83 */
84VMMRCDECL(void) MMGCRamDeregisterTrapHandler(PVM pVM)
85{
86 TRPMGCSetTempHandler(pVM, 0xe, NULL);
87}
88
89
90/**
91 * Read data in guest context with #PF control.
92 *
93 * @returns VBox status.
94 * @param pVM The VM handle.
95 * @param pDst Where to store the readed data.
96 * @param pSrc Pointer to the data to read.
97 * @param cb Size of data to read, only 1/2/4/8 is valid.
98 */
99VMMRCDECL(int) MMGCRamRead(PVM pVM, void *pDst, void *pSrc, size_t cb)
100{
101 int rc;
102 PVMCPU pVCpu = VMMGetCpu0(pVM);
103
104 TRPMSaveTrap(pVCpu); /* save the current trap info, because it will get trashed if our access failed. */
105
106 MMGCRamRegisterTrapHandler(pVM);
107 rc = MMGCRamReadNoTrapHandler(pDst, pSrc, cb);
108 MMGCRamDeregisterTrapHandler(pVM);
109 if (RT_FAILURE(rc))
110 TRPMRestoreTrap(pVCpu);
111
112 return rc;
113}
114
115
116/**
117 * Write data in guest context with #PF control.
118 *
119 * @returns VBox status.
120 * @param pVM The VM handle.
121 * @param pDst Where to write the data.
122 * @param pSrc Pointer to the data to write.
123 * @param cb Size of data to write, only 1/2/4 is valid.
124 */
125VMMRCDECL(int) MMGCRamWrite(PVM pVM, void *pDst, void *pSrc, size_t cb)
126{
127 PVMCPU pVCpu = VMMGetCpu0(pVM);
128 TRPMSaveTrap(pVCpu); /* save the current trap info, because it will get trashed if our access failed. */
129
130 MMGCRamRegisterTrapHandler(pVM);
131 int rc = MMGCRamWriteNoTrapHandler(pDst, pSrc, cb);
132 MMGCRamDeregisterTrapHandler(pVM);
133 if (RT_FAILURE(rc))
134 TRPMRestoreTrap(pVCpu);
135
136 /*
137 * And mark the relevant guest page as accessed and dirty.
138 */
139 PGMGstModifyPage(VMMGetCpu0(pVM), (RTGCPTR)(RTRCUINTPTR)pDst, cb, X86_PTE_A | X86_PTE_D, ~(uint64_t)(X86_PTE_A | X86_PTE_D));
140
141 return rc;
142}
143
144
145/**
146 * \#PF Handler for servicing traps inside MMGCRamReadNoTrapHandler and MMGCRamWriteNoTrapHandler functions.
147 *
148 * @internal
149 */
150DECLCALLBACK(int) mmGCRamTrap0eHandler(PVM pVM, PCPUMCTXCORE pRegFrame)
151{
152 /*
153 * Page fault inside MMGCRamRead()? Resume at *_Error.
154 */
155 if ( (uintptr_t)&MMGCRamReadNoTrapHandler < (uintptr_t)pRegFrame->eip
156 && (uintptr_t)pRegFrame->eip < (uintptr_t)&MMGCRamReadNoTrapHandler_EndProc)
157 {
158 /* Must be a read violation. */
159 AssertReturn(!(TRPMGetErrorCode(VMMGetCpu0(pVM)) & X86_TRAP_PF_RW), VERR_INTERNAL_ERROR);
160 pRegFrame->eip = (uintptr_t)&MMGCRamRead_Error;
161 return VINF_SUCCESS;
162 }
163
164 /*
165 * Page fault inside MMGCRamWrite()? Resume at _Error.
166 */
167 if ( (uintptr_t)&MMGCRamWriteNoTrapHandler < (uintptr_t)pRegFrame->eip
168 && (uintptr_t)pRegFrame->eip < (uintptr_t)&MMGCRamWriteNoTrapHandler_EndProc)
169 {
170 /* Must be a write violation. */
171 AssertReturn(TRPMGetErrorCode(VMMGetCpu0(pVM)) & X86_TRAP_PF_RW, VERR_INTERNAL_ERROR);
172 pRegFrame->eip = (uintptr_t)&MMGCRamWrite_Error;
173 return VINF_SUCCESS;
174 }
175
176 /*
177 * Page fault inside EMGCEmulateLockCmpXchg()? Resume at _Error.
178 */
179 if ( (uintptr_t)&EMGCEmulateLockCmpXchg < (uintptr_t)pRegFrame->eip
180 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateLockCmpXchg_EndProc)
181 {
182 pRegFrame->eip = (uintptr_t)&EMGCEmulateLockCmpXchg_Error;
183 return VINF_SUCCESS;
184 }
185
186 /*
187 * Page fault inside EMGCEmulateCmpXchg()? Resume at _Error.
188 */
189 if ( (uintptr_t)&EMGCEmulateCmpXchg < (uintptr_t)pRegFrame->eip
190 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateCmpXchg_EndProc)
191 {
192 pRegFrame->eip = (uintptr_t)&EMGCEmulateCmpXchg_Error;
193 return VINF_SUCCESS;
194 }
195
196 /*
197 * Page fault inside EMGCEmulateLockCmpXchg8b()? Resume at _Error.
198 */
199 if ( (uintptr_t)&EMGCEmulateLockCmpXchg8b < (uintptr_t)pRegFrame->eip
200 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateLockCmpXchg8b_EndProc)
201 {
202 pRegFrame->eip = (uintptr_t)&EMGCEmulateLockCmpXchg8b_Error;
203 return VINF_SUCCESS;
204 }
205
206 /*
207 * Page fault inside EMGCEmulateCmpXchg8b()? Resume at _Error.
208 */
209 if ( (uintptr_t)&EMGCEmulateCmpXchg8b < (uintptr_t)pRegFrame->eip
210 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateCmpXchg8b_EndProc)
211 {
212 pRegFrame->eip = (uintptr_t)&EMGCEmulateCmpXchg8b_Error;
213 return VINF_SUCCESS;
214 }
215
216 /*
217 * Page fault inside EMGCEmulateLockXAdd()? Resume at _Error.
218 */
219 if ( (uintptr_t)&EMGCEmulateLockXAdd < (uintptr_t)pRegFrame->eip
220 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateLockXAdd_EndProc)
221 {
222 pRegFrame->eip = (uintptr_t)&EMGCEmulateLockXAdd_Error;
223 return VINF_SUCCESS;
224 }
225
226 /*
227 * Page fault inside EMGCEmulateXAdd()? Resume at _Error.
228 */
229 if ( (uintptr_t)&EMGCEmulateXAdd < (uintptr_t)pRegFrame->eip
230 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateXAdd_EndProc)
231 {
232 pRegFrame->eip = (uintptr_t)&EMGCEmulateXAdd_Error;
233 return VINF_SUCCESS;
234 }
235
236 /*
237 * Page fault inside EMEmulateLockOr()? Resume at *_Error.
238 */
239 if ( (uintptr_t)&EMEmulateLockOr < (uintptr_t)pRegFrame->eip
240 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMEmulateLockOr_EndProc)
241 {
242 pRegFrame->eip = (uintptr_t)&EMEmulateLockOr_Error;
243 return VINF_SUCCESS;
244 }
245
246 /*
247 * Page fault inside EMEmulateLockBtr()? Resume at *_Error.
248 */
249 if ( (uintptr_t)&EMEmulateLockBtr < (uintptr_t)pRegFrame->eip
250 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMEmulateLockBtr_EndProc)
251 {
252 pRegFrame->eip = (uintptr_t)&EMEmulateLockBtr_Error;
253 return VINF_SUCCESS;
254 }
255
256 /*
257 * #PF is not handled - cause guru meditation.
258 */
259 return VERR_INTERNAL_ERROR;
260}
261
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette