VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/REMAll.cpp@ 37529

Last change on this file since 37529 was 35346, checked in by vboxsync, 14 years ago

VMM reorg: Moving the public include files from include/VBox to include/VBox/vmm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.2 KB
Line 
1/* $Id: REMAll.cpp 35346 2010-12-27 16:13:13Z vboxsync $ */
2/** @file
3 * REM - Recompiled Execution Monitor, all Contexts part.
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_REM
23#include <VBox/vmm/rem.h>
24#include <VBox/vmm/em.h>
25#include <VBox/vmm/vmm.h>
26#include "REMInternal.h"
27#include <VBox/vmm/vm.h>
28#include <VBox/err.h>
29#include <VBox/log.h>
30
31#include <iprt/asm.h>
32#include <iprt/assert.h>
33
34
35#ifndef IN_RING3
36
37/**
38 * Records a invlpg instruction for replaying upon REM entry.
39 *
40 * @param pVM The VM handle.
41 * @param GCPtrPage The
42 */
43VMMDECL(void) REMNotifyInvalidatePage(PVM pVM, RTGCPTR GCPtrPage)
44{
45 /*
46 * Try take the REM lock and push the address onto the array.
47 */
48 if ( pVM->rem.s.cInvalidatedPages < RT_ELEMENTS(pVM->rem.s.aGCPtrInvalidatedPages)
49 && EMTryEnterRemLock(pVM) == VINF_SUCCESS)
50 {
51 uint32_t iPage = pVM->rem.s.cInvalidatedPages;
52 if (iPage < RT_ELEMENTS(pVM->rem.s.aGCPtrInvalidatedPages))
53 {
54 ASMAtomicWriteU32(&pVM->rem.s.cInvalidatedPages, iPage + 1);
55 pVM->rem.s.aGCPtrInvalidatedPages[iPage] = GCPtrPage;
56
57 EMRemUnlock(pVM);
58 return;
59 }
60
61 CPUMSetChangedFlags(VMMGetCpu(pVM), CPUM_CHANGED_GLOBAL_TLB_FLUSH); /** @todo this array should be per-cpu technically speaking. */
62 ASMAtomicWriteU32(&pVM->rem.s.cInvalidatedPages, 0); /** @todo leave this alone? Optimize this code? */
63
64 EMRemUnlock(pVM);
65 }
66 else
67 {
68 /* Fallback: Simply tell the recompiler to flush its TLB. */
69 CPUMSetChangedFlags(VMMGetCpu(pVM), CPUM_CHANGED_GLOBAL_TLB_FLUSH);
70 ASMAtomicWriteU32(&pVM->rem.s.cInvalidatedPages, 0); /** @todo leave this alone?! Optimize this code? */
71 }
72
73 return;
74}
75
76
77/**
78 * Insert pending notification
79 *
80 * @param pVM VM Handle.
81 * @param pRec Notification record to insert
82 */
83static void remNotifyHandlerInsert(PVM pVM, PREMHANDLERNOTIFICATION pRec)
84{
85 /*
86 * Fetch a free record.
87 */
88 uint32_t cFlushes = 0;
89 uint32_t idxFree;
90 PREMHANDLERNOTIFICATION pFree;
91 do
92 {
93 idxFree = ASMAtomicUoReadU32(&pVM->rem.s.idxFreeList);
94 if (idxFree == UINT32_MAX)
95 {
96 do
97 {
98 cFlushes++;
99 Assert(cFlushes != 128);
100 AssertFatal(cFlushes < _1M);
101 VMMRZCallRing3NoCpu(pVM, VMMCALLRING3_REM_REPLAY_HANDLER_NOTIFICATIONS, 0);
102 idxFree = ASMAtomicUoReadU32(&pVM->rem.s.idxFreeList);
103 } while (idxFree == UINT32_MAX);
104 }
105 pFree = &pVM->rem.s.aHandlerNotifications[idxFree];
106 } while (!ASMAtomicCmpXchgU32(&pVM->rem.s.idxFreeList, pFree->idxNext, idxFree));
107
108 /*
109 * Copy the record.
110 */
111 pFree->enmKind = pRec->enmKind;
112 pFree->u = pRec->u;
113
114 /*
115 * Insert it into the pending list.
116 */
117 uint32_t idxNext;
118 do
119 {
120 idxNext = ASMAtomicUoReadU32(&pVM->rem.s.idxPendingList);
121 ASMAtomicWriteU32(&pFree->idxNext, idxNext);
122 ASMCompilerBarrier();
123 } while (!ASMAtomicCmpXchgU32(&pVM->rem.s.idxPendingList, idxFree, idxNext));
124
125 VM_FF_SET(pVM, VM_FF_REM_HANDLER_NOTIFY);
126}
127
128
129/**
130 * Notification about a successful PGMR3HandlerPhysicalRegister() call.
131 *
132 * @param pVM VM Handle.
133 * @param enmType Handler type.
134 * @param GCPhys Handler range address.
135 * @param cb Size of the handler range.
136 * @param fHasHCHandler Set if the handler have a HC callback function.
137 */
138VMMDECL(void) REMNotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler)
139{
140 REMHANDLERNOTIFICATION Rec;
141 Rec.enmKind = REMHANDLERNOTIFICATIONKIND_PHYSICAL_REGISTER;
142 Rec.u.PhysicalRegister.enmType = enmType;
143 Rec.u.PhysicalRegister.GCPhys = GCPhys;
144 Rec.u.PhysicalRegister.cb = cb;
145 Rec.u.PhysicalRegister.fHasHCHandler = fHasHCHandler;
146 remNotifyHandlerInsert(pVM, &Rec);
147}
148
149
150/**
151 * Notification about a successful PGMR3HandlerPhysicalDeregister() operation.
152 *
153 * @param pVM VM Handle.
154 * @param enmType Handler type.
155 * @param GCPhys Handler range address.
156 * @param cb Size of the handler range.
157 * @param fHasHCHandler Set if the handler have a HC callback function.
158 * @param fRestoreAsRAM Whether the to restore it as normal RAM or as unassigned memory.
159 */
160VMMDECL(void) REMNotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM)
161{
162 REMHANDLERNOTIFICATION Rec;
163 Rec.enmKind = REMHANDLERNOTIFICATIONKIND_PHYSICAL_DEREGISTER;
164 Rec.u.PhysicalDeregister.enmType = enmType;
165 Rec.u.PhysicalDeregister.GCPhys = GCPhys;
166 Rec.u.PhysicalDeregister.cb = cb;
167 Rec.u.PhysicalDeregister.fHasHCHandler = fHasHCHandler;
168 Rec.u.PhysicalDeregister.fRestoreAsRAM = fRestoreAsRAM;
169 remNotifyHandlerInsert(pVM, &Rec);
170}
171
172
173/**
174 * Notification about a successful PGMR3HandlerPhysicalModify() call.
175 *
176 * @param pVM VM Handle.
177 * @param enmType Handler type.
178 * @param GCPhysOld Old handler range address.
179 * @param GCPhysNew New handler range address.
180 * @param cb Size of the handler range.
181 * @param fHasHCHandler Set if the handler have a HC callback function.
182 * @param fRestoreAsRAM Whether the to restore it as normal RAM or as unassigned memory.
183 */
184VMMDECL(void) REMNotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhysOld, RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM)
185{
186 REMHANDLERNOTIFICATION Rec;
187 Rec.enmKind = REMHANDLERNOTIFICATIONKIND_PHYSICAL_MODIFY;
188 Rec.u.PhysicalModify.enmType = enmType;
189 Rec.u.PhysicalModify.GCPhysOld = GCPhysOld;
190 Rec.u.PhysicalModify.GCPhysNew = GCPhysNew;
191 Rec.u.PhysicalModify.cb = cb;
192 Rec.u.PhysicalModify.fHasHCHandler = fHasHCHandler;
193 Rec.u.PhysicalModify.fRestoreAsRAM = fRestoreAsRAM;
194 remNotifyHandlerInsert(pVM, &Rec);
195}
196
197#endif /* !IN_RING3 */
198
199#ifdef IN_RC
200/**
201 * Flushes the physical handler notifications if the queue is almost full.
202 *
203 * This is for avoiding trouble in RC when changing CR3.
204 *
205 * @param pVM The VM handle.
206 * @param pVCpu The virtual CPU handle of the calling EMT.
207 */
208VMMDECL(void) REMNotifyHandlerPhysicalFlushIfAlmostFull(PVM pVM, PVMCPU pVCpu)
209{
210 Assert(pVM->cCpus == 1);
211
212 /*
213 * Less than 48 items means we should flush.
214 */
215 uint32_t cFree = 0;
216 for (uint32_t idx = pVM->rem.s.idxFreeList;
217 idx != UINT32_MAX;
218 idx = pVM->rem.s.aHandlerNotifications[idx].idxNext)
219 {
220 Assert(idx < RT_ELEMENTS(pVM->rem.s.aHandlerNotifications));
221 if (++cFree >= 48)
222 return;
223 }
224 AssertRelease(VM_FF_ISSET(pVM, VM_FF_REM_HANDLER_NOTIFY));
225 AssertRelease(pVM->rem.s.idxPendingList != UINT32_MAX);
226
227 /* Ok, we gotta flush them. */
228 VMMRZCallRing3NoCpu(pVM, VMMCALLRING3_REM_REPLAY_HANDLER_NOTIFICATIONS, 0);
229
230 AssertRelease(pVM->rem.s.idxPendingList == UINT32_MAX);
231 AssertRelease(pVM->rem.s.idxFreeList != UINT32_MAX);
232}
233#endif /* IN_RC */
234
235
236/**
237 * Make REM flush all translation block upon the next call to REMR3State().
238 *
239 * @param pVM Pointer to the shared VM structure.
240 */
241VMMDECL(void) REMFlushTBs(PVM pVM)
242{
243 LogFlow(("REMFlushTBs: fFlushTBs=%RTbool fInREM=%RTbool fInStateSync=%RTbool\n",
244 pVM->rem.s.fFlushTBs, pVM->rem.s.fInREM, pVM->rem.s.fInStateSync));
245 pVM->rem.s.fFlushTBs = true;
246}
247
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