VirtualBox

source: vbox/trunk/src/VBox/VMM/PGMGst.h@ 7821

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

Renamed PDPTR to PDPT.
Added preliminary code for executing code with X86_CR0_WP cleared (disabled).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 19.4 KB
Line 
1/* $Id: PGMGst.h 7715 2008-04-03 09:03:01Z vboxsync $ */
2/** @file
3 * VBox - Page Manager / Monitor, Guest Paging Template.
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* Defined Constants And Macros *
20*******************************************************************************/
21#undef GSTPT
22#undef PGSTPT
23#undef GSTPTE
24#undef PGSTPTE
25#undef GSTPD
26#undef PGSTPD
27#undef GSTPDE
28#undef PGSTPDE
29#undef GST_BIG_PAGE_SIZE
30#undef GST_BIG_PAGE_OFFSET_MASK
31#undef GST_PDE_PG_MASK
32#undef GST_PDE_BIG_PG_MASK
33#undef GST_PD_SHIFT
34#undef GST_PD_MASK
35#undef GST_PTE_PG_MASK
36#undef GST_PT_SHIFT
37#undef GST_PT_MASK
38#undef GST_TOTAL_PD_ENTRIES
39#undef GST_CR3_PAGE_MASK
40#undef GST_PDPE_ENTRIES
41
42#if PGM_GST_TYPE == PGM_TYPE_32BIT \
43 || PGM_GST_TYPE == PGM_TYPE_REAL \
44 || PGM_GST_TYPE == PGM_TYPE_PROT
45# define GSTPT X86PT
46# define PGSTPT PX86PT
47# define GSTPTE X86PTE
48# define PGSTPTE PX86PTE
49# define GSTPD X86PD
50# define PGSTPD PX86PD
51# define GSTPDE X86PDE
52# define PGSTPDE PX86PDE
53# define GST_BIG_PAGE_SIZE X86_PAGE_4M_SIZE
54# define GST_BIG_PAGE_OFFSET_MASK X86_PAGE_4M_OFFSET_MASK
55# define GST_PDE_PG_MASK X86_PDE_PG_MASK
56# define GST_PDE_BIG_PG_MASK X86_PDE4M_PG_MASK
57# define GST_PD_SHIFT X86_PD_SHIFT
58# define GST_PD_MASK X86_PD_MASK
59# define GST_TOTAL_PD_ENTRIES X86_PG_ENTRIES
60# define GST_PTE_PG_MASK X86_PTE_PG_MASK
61# define GST_PT_SHIFT X86_PT_SHIFT
62# define GST_PT_MASK X86_PT_MASK
63# define GST_CR3_PAGE_MASK X86_CR3_PAGE_MASK
64#elif PGM_GST_TYPE == PGM_TYPE_PAE \
65 || PGM_GST_TYPE == PGM_TYPE_AMD64
66# define GSTPT X86PTPAE
67# define PGSTPT PX86PTPAE
68# define GSTPTE X86PTEPAE
69# define PGSTPTE PX86PTEPAE
70# define GSTPD X86PDPAE
71# define PGSTPD PX86PDPAE
72# define GSTPDE X86PDEPAE
73# define PGSTPDE PX86PDEPAE
74# define GST_BIG_PAGE_SIZE X86_PAGE_2M_SIZE
75# define GST_BIG_PAGE_OFFSET_MASK X86_PAGE_2M_OFFSET_MASK
76# define GST_PDE_PG_MASK X86_PDE_PAE_PG_MASK
77# define GST_PDE_BIG_PG_MASK X86_PDE2M_PAE_PG_MASK
78# define GST_PD_SHIFT X86_PD_PAE_SHIFT
79# define GST_PD_MASK X86_PD_PAE_MASK
80# if PGM_GST_TYPE == PGM_TYPE_PAE
81# define GST_TOTAL_PD_ENTRIES (X86_PG_PAE_ENTRIES * X86_PG_PAE_PDPE_ENTRIES)
82# define GST_PDPE_ENTRIES X86_PG_PAE_PDPE_ENTRIES
83# else
84# define GST_TOTAL_PD_ENTRIES (X86_PG_AMD64_ENTRIES * X86_PG_AMD64_PDPE_ENTRIES)
85# define GST_PDPE_ENTRIES X86_PG_AMD64_PDPE_ENTRIES
86# endif
87# define GST_PTE_PG_MASK X86_PTE_PAE_PG_MASK
88# define GST_PT_SHIFT X86_PT_PAE_SHIFT
89# define GST_PT_MASK X86_PT_PAE_MASK
90# define GST_CR3_PAGE_MASK X86_CR3_PAE_PAGE_MASK
91#endif
92
93
94/*******************************************************************************
95* Internal Functions *
96*******************************************************************************/
97__BEGIN_DECLS
98/* r3 */
99PGM_GST_DECL(int, InitData)(PVM pVM, PPGMMODEDATA pModeData, bool fResolveGCAndR0);
100PGM_GST_DECL(int, Enter)(PVM pVM, RTGCPHYS GCPhysCR3);
101PGM_GST_DECL(int, Relocate)(PVM pVM, RTGCUINTPTR offDelta);
102PGM_GST_DECL(int, Exit)(PVM pVM);
103
104static DECLCALLBACK(int) pgmR3Gst32BitWriteHandlerCR3(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser);
105static DECLCALLBACK(int) pgmR3GstPAEWriteHandlerCR3(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser);
106#if 0
107static DECLCALLBACK(int) pgmR3GstPAEWriteHandlerPD(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser);
108#endif
109
110/* all */
111PGM_GST_DECL(int, GetPage)(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys);
112PGM_GST_DECL(int, ModifyPage)(PVM pVM, RTGCUINTPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask);
113PGM_GST_DECL(int, GetPDE)(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPDE);
114PGM_GST_DECL(int, MapCR3)(PVM pVM, RTGCPHYS GCPhysCR3);
115PGM_GST_DECL(int, UnmapCR3)(PVM pVM);
116PGM_GST_DECL(int, MonitorCR3)(PVM pVM, RTGCPHYS GCPhysCR3);
117PGM_GST_DECL(int, UnmonitorCR3)(PVM pVM);
118__END_DECLS
119
120
121/**
122 * Initializes the guest bit of the paging mode data.
123 *
124 * @returns VBox status code.
125 * @param pVM The VM handle.
126 * @param fResolveGCAndR0 Indicate whether or not GC and Ring-0 symbols can be resolved now.
127 * This is used early in the init process to avoid trouble with PDM
128 * not being initialized yet.
129 */
130PGM_GST_DECL(int, InitData)(PVM pVM, PPGMMODEDATA pModeData, bool fResolveGCAndR0)
131{
132 Assert(pModeData->uGstType == PGM_GST_TYPE);
133
134 /* Ring-3 */
135 pModeData->pfnR3GstRelocate = PGM_GST_NAME(Relocate);
136 pModeData->pfnR3GstExit = PGM_GST_NAME(Exit);
137 pModeData->pfnR3GstGetPDE = PGM_GST_NAME(GetPDE);
138 pModeData->pfnR3GstGetPage = PGM_GST_NAME(GetPage);
139 pModeData->pfnR3GstModifyPage = PGM_GST_NAME(ModifyPage);
140 pModeData->pfnR3GstMapCR3 = PGM_GST_NAME(MapCR3);
141 pModeData->pfnR3GstUnmapCR3 = PGM_GST_NAME(UnmapCR3);
142 pModeData->pfnR3GstMonitorCR3 = PGM_GST_NAME(MonitorCR3);
143 pModeData->pfnR3GstUnmonitorCR3 = PGM_GST_NAME(UnmonitorCR3);
144
145#if PGM_GST_TYPE == PGM_TYPE_32BIT || PGM_GST_TYPE == PGM_TYPE_PAE
146 pModeData->pfnR3GstWriteHandlerCR3 = PGM_GST_NAME(WriteHandlerCR3);
147 pModeData->pszR3GstWriteHandlerCR3 = "Guest CR3 Write access handler";
148 pModeData->pfnR3GstPAEWriteHandlerCR3 = PGM_GST_NAME(WriteHandlerCR3);
149 pModeData->pszR3GstPAEWriteHandlerCR3 = "Guest CR3 Write access handler (PAE)";
150#else
151 pModeData->pfnR3GstWriteHandlerCR3 = NULL;
152 pModeData->pszR3GstWriteHandlerCR3 = NULL;
153 pModeData->pfnR3GstPAEWriteHandlerCR3 = NULL;
154 pModeData->pszR3GstPAEWriteHandlerCR3 = NULL;
155#endif
156
157 if (fResolveGCAndR0)
158 {
159 int rc;
160
161 /* GC */
162 rc = PDMR3GetSymbolGC(pVM, NULL, PGM_GST_NAME_GC_STR(GetPage), &pModeData->pfnGCGstGetPage);
163 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_GC_STR(GetPage), rc), rc);
164 rc = PDMR3GetSymbolGC(pVM, NULL, PGM_GST_NAME_GC_STR(ModifyPage), &pModeData->pfnGCGstModifyPage);
165 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_GC_STR(ModifyPage), rc), rc);
166 rc = PDMR3GetSymbolGC(pVM, NULL, PGM_GST_NAME_GC_STR(GetPDE), &pModeData->pfnGCGstGetPDE);
167 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_GC_STR(GetPDE), rc), rc);
168 rc = PDMR3GetSymbolGC(pVM, NULL, PGM_GST_NAME_GC_STR(MonitorCR3), &pModeData->pfnGCGstMonitorCR3);
169 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_GC_STR(MonitorCR3), rc), rc);
170 rc = PDMR3GetSymbolGC(pVM, NULL, PGM_GST_NAME_GC_STR(UnmonitorCR3), &pModeData->pfnGCGstUnmonitorCR3);
171 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_GC_STR(UnmonitorCR3), rc), rc);
172 rc = PDMR3GetSymbolGC(pVM, NULL, PGM_GST_NAME_GC_STR(MapCR3), &pModeData->pfnGCGstMapCR3);
173 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_GC_STR(MapCR3), rc), rc);
174 rc = PDMR3GetSymbolGC(pVM, NULL, PGM_GST_NAME_GC_STR(UnmapCR3), &pModeData->pfnGCGstUnmapCR3);
175 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_GC_STR(UnmapCR3), rc), rc);
176#if PGM_GST_TYPE == PGM_TYPE_32BIT || PGM_GST_TYPE == PGM_TYPE_PAE
177 rc = PDMR3GetSymbolGC(pVM, NULL, PGM_GST_NAME_GC_STR(WriteHandlerCR3), &pModeData->pfnGCGstWriteHandlerCR3);
178 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_GC_STR(WriteHandlerCR3), rc), rc);
179 rc = PDMR3GetSymbolGC(pVM, NULL, PGM_GST_NAME_GC_STR(WriteHandlerCR3), &pModeData->pfnGCGstPAEWriteHandlerCR3);
180 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_GC_STR(PAEWriteHandlerCR3), rc), rc);
181#endif
182
183 /* Ring-0 */
184 rc = PDMR3GetSymbolR0(pVM, NULL, PGM_GST_NAME_R0_STR(GetPage), &pModeData->pfnR0GstGetPage);
185 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_R0_STR(GetPage), rc), rc);
186 rc = PDMR3GetSymbolR0(pVM, NULL, PGM_GST_NAME_R0_STR(ModifyPage), &pModeData->pfnR0GstModifyPage);
187 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_R0_STR(ModifyPage), rc), rc);
188 rc = PDMR3GetSymbolR0(pVM, NULL, PGM_GST_NAME_R0_STR(GetPDE), &pModeData->pfnR0GstGetPDE);
189 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_R0_STR(GetPDE), rc), rc);
190 rc = PDMR3GetSymbolR0(pVM, NULL, PGM_GST_NAME_R0_STR(MonitorCR3), &pModeData->pfnR0GstMonitorCR3);
191 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_R0_STR(MonitorCR3), rc), rc);
192 rc = PDMR3GetSymbolR0(pVM, NULL, PGM_GST_NAME_R0_STR(UnmonitorCR3), &pModeData->pfnR0GstUnmonitorCR3);
193 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_R0_STR(UnmonitorCR3), rc), rc);
194 rc = PDMR3GetSymbolR0(pVM, NULL, PGM_GST_NAME_R0_STR(MapCR3), &pModeData->pfnR0GstMapCR3);
195 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_R0_STR(MapCR3), rc), rc);
196 rc = PDMR3GetSymbolR0(pVM, NULL, PGM_GST_NAME_R0_STR(UnmapCR3), &pModeData->pfnR0GstUnmapCR3);
197 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_R0_STR(UnmapCR3), rc), rc);
198#if PGM_GST_TYPE == PGM_TYPE_32BIT || PGM_GST_TYPE == PGM_TYPE_PAE
199 rc = PDMR3GetSymbolR0(pVM, NULL, PGM_GST_NAME_R0_STR(WriteHandlerCR3), &pModeData->pfnR0GstWriteHandlerCR3);
200 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_R0_STR(WriteHandlerCR3), rc), rc);
201 rc = PDMR3GetSymbolR0(pVM, NULL, PGM_GST_NAME_R0_STR(WriteHandlerCR3), &pModeData->pfnR0GstPAEWriteHandlerCR3);
202 AssertMsgRCReturn(rc, ("%s -> rc=%Vrc\n", PGM_GST_NAME_R0_STR(PAEWriteHandlerCR3), rc), rc);
203#endif
204 }
205
206 return VINF_SUCCESS;
207}
208
209
210/**
211 * Enters the guest mode.
212 *
213 * @returns VBox status code.
214 * @param pVM VM handle.
215 * @param GCPhysCR3 The physical address from the CR3 register.
216 */
217PGM_GST_DECL(int, Enter)(PVM pVM, RTGCPHYS GCPhysCR3)
218{
219 /*
220 * Map and monitor CR3
221 */
222 int rc = PGM_GST_NAME(MapCR3)(pVM, GCPhysCR3);
223 if (VBOX_SUCCESS(rc) && !pVM->pgm.s.fMappingsFixed)
224 rc = PGM_GST_NAME(MonitorCR3)(pVM, GCPhysCR3);
225 return rc;
226}
227
228
229/**
230 * Relocate any GC pointers related to guest mode paging.
231 *
232 * @returns VBox status code.
233 * @param pVM The VM handle.
234 * @param offDelta The reloation offset.
235 */
236PGM_GST_DECL(int, Relocate)(PVM pVM, RTGCUINTPTR offDelta)
237{
238 /* nothing special to do here - InitData does the job. */
239 return VINF_SUCCESS;
240}
241
242
243/**
244 * Exits the guest mode.
245 *
246 * @returns VBox status code.
247 * @param pVM VM handle.
248 */
249PGM_GST_DECL(int, Exit)(PVM pVM)
250{
251 int rc = PGM_GST_NAME(UnmonitorCR3)(pVM);
252 if (VBOX_SUCCESS(rc))
253 rc = PGM_GST_NAME(UnmapCR3)(pVM);
254 return rc;
255}
256
257
258#if PGM_GST_TYPE == PGM_TYPE_32BIT
259/**
260 * Physical write access for the Guest CR3 in 32-bit mode.
261 *
262 * @returns VINF_SUCCESS if the handler have carried out the operation.
263 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
264 * @param pVM VM Handle.
265 * @param GCPhys The physical address the guest is writing to.
266 * @param pvPhys The HC mapping of that address.
267 * @param pvBuf What the guest is reading/writing.
268 * @param cbBuf How much it's reading/writing.
269 * @param enmAccessType The access type.
270 * @param pvUser User argument.
271 */
272static DECLCALLBACK(int) pgmR3Gst32BitWriteHandlerCR3(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
273{
274 AssertMsg(!pVM->pgm.s.fMappingsFixed, ("Shouldn't be registered when mappings are fixed!\n"));
275 Assert(enmAccessType == PGMACCESSTYPE_WRITE);
276 Log2(("pgmR3Gst32BitWriteHandlerCR3: ff=%#x GCPhys=%VGp pvPhys=%p cbBuf=%d pvBuf={%.*Vhxs}\n", pVM->fForcedActions, GCPhys, pvPhys, cbBuf, cbBuf, pvBuf));
277
278 /*
279 * Do the write operation.
280 */
281 memcpy(pvPhys, pvBuf, cbBuf);
282 if ( !pVM->pgm.s.fMappingsFixed
283 && !VM_FF_ISPENDING(pVM, VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL))
284 {
285 /*
286 * Check for conflicts.
287 */
288 const RTGCUINTPTR offPD = GCPhys & PAGE_OFFSET_MASK;
289 const unsigned iPD1 = offPD / sizeof(X86PDE);
290 const unsigned iPD2 = (offPD + cbBuf - 1) / sizeof(X86PDE);
291 Assert(iPD1 - iPD2 <= 1);
292 if ( ( pVM->pgm.s.pGuestPDHC->a[iPD1].n.u1Present
293 && pgmGetMapping(pVM, iPD1 << X86_PD_SHIFT) )
294 || ( iPD1 != iPD2
295 && pVM->pgm.s.pGuestPDHC->a[iPD2].n.u1Present
296 && pgmGetMapping(pVM, iPD2 << X86_PD_SHIFT) )
297 )
298 {
299 Log(("pgmR3Gst32BitWriteHandlerCR3: detected conflict. iPD1=%#x iPD2=%#x GCPhys=%VGp\n", iPD1, iPD2, GCPhys));
300 STAM_COUNTER_INC(&pVM->pgm.s.StatHCGuestPDWriteConflict);
301 VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
302 }
303 }
304
305 STAM_COUNTER_INC(&pVM->pgm.s.StatHCGuestPDWrite);
306 return VINF_SUCCESS;
307}
308#endif /* 32BIT */
309
310
311#if PGM_GST_TYPE == PGM_TYPE_PAE
312/**
313 * Physical write access handler for the Guest CR3 in PAE mode.
314 *
315 * @returns VINF_SUCCESS if the handler have carried out the operation.
316 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
317 * @param pVM VM Handle.
318 * @param GCPhys The physical address the guest is writing to.
319 * @param pvPhys The HC mapping of that address.
320 * @param pvBuf What the guest is reading/writing.
321 * @param cbBuf How much it's reading/writing.
322 * @param enmAccessType The access type.
323 * @param pvUser User argument.
324 */
325static DECLCALLBACK(int) pgmR3GstPAEWriteHandlerCR3(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
326{
327 AssertMsg(!pVM->pgm.s.fMappingsFixed, ("Shouldn't be registered when mappings are fixed!\n"));
328 Assert(enmAccessType == PGMACCESSTYPE_WRITE);
329 Log2(("pgmR3GstPAEWriteHandlerCR3: ff=%#x GCPhys=%VGp pvPhys=%p cbBuf=%d pvBuf={%.*Vhxs}\n", pVM->fForcedActions, GCPhys, pvPhys, cbBuf, cbBuf, pvBuf));
330
331 /*
332 * Do the write operation.
333 */
334 memcpy(pvPhys, pvBuf, cbBuf);
335 if ( !pVM->pgm.s.fMappingsFixed
336 && !VM_FF_ISPENDING(pVM, VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL))
337 {
338 /*
339 * Check if any of the PDs have changed.
340 * We'll simply check all of them instead of figuring out which one/two to check.
341 */
342 for (unsigned i = 0; i < 4; i++)
343 {
344 if ( pVM->pgm.s.pGstPaePDPTHC->a[i].n.u1Present
345 && (pVM->pgm.s.pGstPaePDPTHC->a[i].u & X86_PDPE_PG_MASK) != pVM->pgm.s.aGCPhysGstPaePDsMonitored[i])
346 {
347 Log(("pgmR3GstPAEWriteHandlerCR3: detected updated PDPE; [%d] = %#llx, Old GCPhys=%VGp\n",
348 i, pVM->pgm.s.pGstPaePDPTHC->a[i].u, pVM->pgm.s.aGCPhysGstPaePDsMonitored[i]));
349 /*
350 * The PD has changed.
351 * We will schedule a monitoring update for the next TLB Flush,
352 * InvalidatePage or SyncCR3.
353 *
354 * This isn't perfect, because a lazy page sync might be dealing with an half
355 * updated PDPE. However, we assume that the guest OS is disabling interrupts
356 * and being extremely careful (cmpxchg8b) when updating a PDPE where it's
357 * executing.
358 */
359 pVM->pgm.s.fSyncFlags |= PGM_SYNC_MONITOR_CR3;
360 }
361 }
362 }
363 /*
364 * Flag a updating of the monitor at the next crossroad so we don't monitor the
365 * wrong pages for soo long that they can be reused as code pages and freak out
366 * the recompiler or something.
367 */
368 else
369 pVM->pgm.s.fSyncFlags |= PGM_SYNC_MONITOR_CR3;
370
371
372 STAM_COUNTER_INC(&pVM->pgm.s.StatHCGuestPDWrite);
373 return VINF_SUCCESS;
374}
375
376# if 0
377/**
378 * Physical write access for Guest CR3.
379 *
380 * @returns VINF_SUCCESS if the handler have carried out the operation.
381 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
382 * @param pVM VM Handle.
383 * @param GCPhys The physical address the guest is writing to.
384 * @param pvPhys The HC mapping of that address.
385 * @param pvBuf What the guest is reading/writing.
386 * @param cbBuf How much it's reading/writing.
387 * @param enmAccessType The access type.
388 * @param pvUser User argument.
389 */
390static DECLCALLBACK(int) pgmR3GstPAEWriteHandlerPD(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
391{
392 AssertMsg(!pVM->pgm.s.fMappingsFixed, ("Shouldn't be registered when mappings are fixed!\n"));
393 Assert(enmAccessType == PGMACCESSTYPE_WRITE);
394 Log2(("pgmR3GstPAEWriteHandlerPD: ff=%#x GCPhys=%VGp pvPhys=%p cbBuf=%d pvBuf={%.*Vhxs}\n", pVM->fForcedActions, GCPhys, pvPhys, cbBuf, cbBuf, pvBuf));
395
396 /*
397 * Do the write operation.
398 */
399 memcpy(pvPhys, pvBuf, cbBuf);
400 if ( !pVM->pgm.s.fMappingsFixed
401 && !VM_FF_ISPENDING(pVM, VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL))
402 {
403 /*
404 * Figure out which of the 4 PDs this is.
405 */
406 unsigned i;
407 for (i = 0; i < 4; i++)
408 if (pVM->pgm.s.pGstPaePDPTHC->a[i].u == (GCPhys & X86_PTE_PAE_PG_MASK))
409 {
410 PX86PDPAE pPDSrc = pgmGstGetPaePD(&pVM->pgm.s, i << X86_PDPT_SHIFT);
411 const RTGCUINTPTR offPD = GCPhys & PAGE_OFFSET_MASK;
412 const unsigned iPD1 = offPD / sizeof(X86PDEPAE);
413 const unsigned iPD2 = (offPD + cbBuf - 1) / sizeof(X86PDEPAE);
414 Assert(iPD1 - iPD2 <= 1);
415 if ( ( pPDSrc->a[iPD1].n.u1Present
416 && pgmGetMapping(pVM, (i << X86_PDPT_SHIFT) | (iPD1 << X86_PD_PAE_SHIFT)) )
417 || ( iPD1 != iPD2
418 && pPDSrc->a[iPD2].n.u1Present
419 && pgmGetMapping(pVM, (i << X86_PDPT_SHIFT) | (iPD2 << X86_PD_PAE_SHIFT)) )
420 )
421 {
422 Log(("pgmR3GstPaePD3WriteHandler: detected conflict. i=%d iPD1=%#x iPD2=%#x GCPhys=%VGp\n",
423 i, iPD1, iPD2, GCPhys));
424 STAM_COUNTER_INC(&pVM->pgm.s.StatHCGuestPDWriteConflict);
425 VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
426 }
427 break; /* ASSUMES no duplicate entries... */
428 }
429 Assert(i < 4);
430 }
431
432 STAM_COUNTER_INC(&pVM->pgm.s.StatHCGuestPDWrite);
433 return VINF_SUCCESS;
434}
435# endif
436#endif /* PAE */
437
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