VirtualBox

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

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

Emulate cmpxchg8b in GC.

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