VirtualBox

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

Last change on this file since 7821 was 7286, checked in by vboxsync, 17 years ago

emulate [lock] xadd in GC

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.5 KB
Line 
1/* $Id: MMRamGC.cpp 7286 2008-03-05 08:06:41Z vboxsync $ */
2/** @file
3 * MMRamGC - Guest Context Ram access Routines, pair for MMRamGCA.asm.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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/pgm.h>
30
31#include <iprt/assert.h>
32#include <VBox/param.h>
33#include <VBox/err.h>
34
35
36/*******************************************************************************
37* Internal Functions *
38*******************************************************************************/
39static DECLCALLBACK(int) mmGCRamTrap0eHandler(PVM pVM, PCPUMCTXCORE pRegFrame);
40
41DECLASM(void) MMGCRamReadNoTrapHandler_EndProc(void);
42DECLASM(void) MMGCRamWriteNoTrapHandler_EndProc(void);
43DECLASM(void) EMGCEmulateLockCmpXchg_EndProc(void);
44DECLASM(void) EMGCEmulateLockCmpXchg_Error(void);
45DECLASM(void) EMGCEmulateCmpXchg_EndProc(void);
46DECLASM(void) EMGCEmulateCmpXchg_Error(void);
47DECLASM(void) EMGCEmulateLockXAdd_EndProc(void);
48DECLASM(void) EMGCEmulateLockXAdd_Error(void);
49DECLASM(void) EMGCEmulateXAdd_EndProc(void);
50DECLASM(void) EMGCEmulateXAdd_Error(void);
51DECLASM(void) EMEmulateLockOr_EndProc(void);
52DECLASM(void) EMEmulateLockOr_Error(void);
53DECLASM(void) EMEmulateLockBtr_EndProc(void);
54DECLASM(void) EMEmulateLockBtr_Error(void);
55DECLASM(void) MMGCRamRead_Error(void);
56DECLASM(void) MMGCRamWrite_Error(void);
57
58
59/**
60 * Install MMGCRam Hypervisor page fault handler for normal working
61 * of MMGCRamRead and MMGCRamWrite calls.
62 * This handler will be automatically removed at page fault.
63 * In other case it must be removed by MMGCRamDeregisterTrapHandler call.
64 *
65 * @param pVM VM handle.
66 */
67MMGCDECL(void) MMGCRamRegisterTrapHandler(PVM pVM)
68{
69 TRPMGCSetTempHandler(pVM, 0xe, mmGCRamTrap0eHandler);
70}
71
72/**
73 * Remove MMGCRam Hypervisor page fault handler.
74 * See description of MMGCRamRegisterTrapHandler call.
75 *
76 * @param pVM VM handle.
77 */
78MMGCDECL(void) MMGCRamDeregisterTrapHandler(PVM pVM)
79{
80 TRPMGCSetTempHandler(pVM, 0xe, NULL);
81}
82
83
84/**
85 * Read data in guest context with #PF control.
86 *
87 * @returns VBox status.
88 * @param pVM The VM handle.
89 * @param pDst Where to store the readed data.
90 * @param pSrc Pointer to the data to read.
91 * @param cb Size of data to read, only 1/2/4/8 is valid.
92 */
93MMGCDECL(int) MMGCRamRead(PVM pVM, void *pDst, void *pSrc, size_t cb)
94{
95 int rc;
96
97 TRPMSaveTrap(pVM); /* save the current trap info, because it will get trashed if our access failed. */
98
99 MMGCRamRegisterTrapHandler(pVM);
100 rc = MMGCRamReadNoTrapHandler(pDst, pSrc, cb);
101 MMGCRamDeregisterTrapHandler(pVM);
102 if (VBOX_FAILURE(rc))
103 TRPMRestoreTrap(pVM);
104
105 return rc;
106}
107
108/**
109 * Write data in guest context with #PF control.
110 *
111 * @returns VBox status.
112 * @param pVM The VM handle.
113 * @param pDst Where to write the data.
114 * @param pSrc Pointer to the data to write.
115 * @param cb Size of data to write, only 1/2/4 is valid.
116 */
117MMGCDECL(int) MMGCRamWrite(PVM pVM, void *pDst, void *pSrc, size_t cb)
118{
119 int rc;
120
121 TRPMSaveTrap(pVM); /* save the current trap info, because it will get trashed if our access failed. */
122
123 MMGCRamRegisterTrapHandler(pVM);
124 rc = MMGCRamWriteNoTrapHandler(pDst, pSrc, cb);
125 MMGCRamDeregisterTrapHandler(pVM);
126 if (VBOX_FAILURE(rc))
127 TRPMRestoreTrap(pVM);
128
129 /*
130 * And mark the relevant guest page as accessed and dirty.
131 */
132 PGMGstModifyPage(pVM, pDst, cb, X86_PTE_A | X86_PTE_D, ~(uint64_t)(X86_PTE_A | X86_PTE_D));
133
134 return rc;
135}
136
137
138/**
139 * \#PF Handler for servicing traps inside MMGCRamReadNoTrapHandler and MMGCRamWriteNoTrapHandler functions.
140 *
141 * @internal
142 */
143DECLCALLBACK(int) mmGCRamTrap0eHandler(PVM pVM, PCPUMCTXCORE pRegFrame)
144{
145 /*
146 * Page fault inside MMGCRamRead()? Resume at *_Error.
147 */
148 if ( (uintptr_t)&MMGCRamReadNoTrapHandler < (uintptr_t)pRegFrame->eip
149 && (uintptr_t)pRegFrame->eip < (uintptr_t)&MMGCRamReadNoTrapHandler_EndProc)
150 {
151 /* Must be a read violation. */
152 AssertReturn(!(TRPMGetErrorCode(pVM) & X86_TRAP_PF_RW), VERR_INTERNAL_ERROR);
153 pRegFrame->eip = (uintptr_t)&MMGCRamRead_Error;
154 return VINF_SUCCESS;
155 }
156
157 /*
158 * Page fault inside MMGCRamWrite()? Resume at _Error.
159 */
160 if ( (uintptr_t)&MMGCRamWriteNoTrapHandler < (uintptr_t)pRegFrame->eip
161 && (uintptr_t)pRegFrame->eip < (uintptr_t)&MMGCRamWriteNoTrapHandler_EndProc)
162 {
163 /* Must be a write violation. */
164 AssertReturn(TRPMGetErrorCode(pVM) & X86_TRAP_PF_RW, VERR_INTERNAL_ERROR);
165 pRegFrame->eip = (uintptr_t)&MMGCRamWrite_Error;
166 return VINF_SUCCESS;
167 }
168
169 /*
170 * Page fault inside EMGCEmulateLockCmpXchg()? Resume at _Error.
171 */
172 if ( (uintptr_t)&EMGCEmulateLockCmpXchg < (uintptr_t)pRegFrame->eip
173 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateLockCmpXchg_EndProc)
174 {
175 pRegFrame->eip = (uintptr_t)&EMGCEmulateLockCmpXchg_Error;
176 return VINF_SUCCESS;
177 }
178
179 /*
180 * Page fault inside EMGCEmulateCmpXchg()? Resume at _Error.
181 */
182 if ( (uintptr_t)&EMGCEmulateCmpXchg < (uintptr_t)pRegFrame->eip
183 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateCmpXchg_EndProc)
184 {
185 pRegFrame->eip = (uintptr_t)&EMGCEmulateCmpXchg_Error;
186 return VINF_SUCCESS;
187 }
188
189 /*
190 * Page fault inside EMGCEmulateLockXAdd()? Resume at _Error.
191 */
192 if ( (uintptr_t)&EMGCEmulateLockXAdd < (uintptr_t)pRegFrame->eip
193 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateLockXAdd_EndProc)
194 {
195 pRegFrame->eip = (uintptr_t)&EMGCEmulateLockXAdd_Error;
196 return VINF_SUCCESS;
197 }
198
199 /*
200 * Page fault inside EMGCEmulateXAdd()? Resume at _Error.
201 */
202 if ( (uintptr_t)&EMGCEmulateXAdd < (uintptr_t)pRegFrame->eip
203 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateXAdd_EndProc)
204 {
205 pRegFrame->eip = (uintptr_t)&EMGCEmulateXAdd_Error;
206 return VINF_SUCCESS;
207 }
208
209 /*
210 * Page fault inside EMEmulateLockOr()? Resume at *_Error.
211 */
212 if ( (uintptr_t)&EMEmulateLockOr < (uintptr_t)pRegFrame->eip
213 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMEmulateLockOr_EndProc)
214 {
215 pRegFrame->eip = (uintptr_t)&EMEmulateLockOr_Error;
216 return VINF_SUCCESS;
217 }
218
219 /*
220 * Page fault inside EMEmulateLockBtr()? Resume at *_Error.
221 */
222 if ( (uintptr_t)&EMEmulateLockBtr < (uintptr_t)pRegFrame->eip
223 && (uintptr_t)pRegFrame->eip < (uintptr_t)&EMEmulateLockBtr_EndProc)
224 {
225 pRegFrame->eip = (uintptr_t)&EMEmulateLockBtr_Error;
226 return VINF_SUCCESS;
227 }
228
229 /*
230 * #PF is not handled - cause guru meditation.
231 */
232 return VERR_INTERNAL_ERROR;
233}
234
235
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