VirtualBox

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

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

More ring-0/ring-3 type safety (callbacks and PDM symbol resolving).

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