VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMGC/PGMGCGst.h@ 1

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
Line 
1/** @file
2 *
3 * VBox - Page Manager, Guest Paging Template - Guest Context.
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
86PGMGCDECL(int) pgmGCGst32BitWriteHandlerCR3(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser);
87PGMGCDECL(int) pgmGCGstPAEWriteHandlerCR3(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser);
88PGMGCDECL(int) pgmGCGstPAEWriteHandlerPD(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser);
89__END_DECLS
90
91
92#if PGM_GST_TYPE == PGM_TYPE_32BIT
93
94/**
95 * Write access handler for the Guest CR3 page in 32-bit mode.
96 *
97 * This will try interpret the instruction, if failure fail back to the recompiler.
98 * Check if the changed PDEs are marked present and conflicts with our
99 * mappings. If conflict, we'll switch to the host context and resolve it there
100 *
101 * @returns VBox status code (appropritate for trap handling and GC return).
102 * @param pVM VM Handle.
103 * @param uErrorCode CPU Error code.
104 * @param pRegFrame Trap register frame.
105 * @param pvFault The fault address (cr2).
106 * @param GCPhysFault The GC physical address corresponding to pvFault.
107 * @param pvUser User argument.
108 */
109PGMGCDECL(int) pgmGCGst32BitWriteHandlerCR3(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser)
110{
111 AssertMsg(!pVM->pgm.s.fMappingsFixed, ("Shouldn't be registered when mappings are fixed!\n"));
112
113 /*
114 * Try interpret the instruction.
115 */
116 uint32_t cb;
117 int rc = EMInterpretInstruction(pVM, pRegFrame, pvFault, &cb);
118 if (VBOX_SUCCESS(rc) && cb)
119 {
120 /*
121 * Check if the modified PDEs are present and mappings.
122 */
123 const RTGCUINTPTR offPD = GCPhysFault & PAGE_OFFSET_MASK;
124 const unsigned iPD1 = offPD / sizeof(X86PDE);
125 const unsigned iPD2 = (offPD + cb - 1) / sizeof(X86PDE);
126
127 Assert(cb > 0 && cb <= 8);
128 Assert(iPD1 < ELEMENTS(pVM->pgm.s.pGuestPDGC->a));
129 Assert(iPD2 < ELEMENTS(pVM->pgm.s.pGuestPDGC->a));
130
131#ifdef DEBUG
132 Log(("pgmGCGst32BitWriteHandlerCR3: emulated change to PD %#x addr=%VGv\n", iPD1, iPD1 << X86_PD_SHIFT));
133 if (iPD1 != iPD2)
134 Log(("pgmGCGst32BitWriteHandlerCR3: emulated change to PD %#x addr=%VGv\n", iPD2, iPD2 << X86_PD_SHIFT));
135#endif
136
137 if (!pVM->pgm.s.fMappingsFixed)
138 {
139 PX86PD pPDSrc = pVM->pgm.s.pGuestPDGC;
140 if ( ( pPDSrc->a[iPD1].n.u1Present
141 && pgmGetMapping(pVM, (RTGCPTR)(iPD1 << X86_PD_SHIFT)) )
142 || ( iPD1 != iPD2
143 && pPDSrc->a[iPD2].n.u1Present
144 && pgmGetMapping(pVM, (RTGCPTR)(iPD2 << X86_PD_SHIFT)) )
145 )
146 {
147 STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestCR3WriteConflict);
148 VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
149 if (rc == VINF_SUCCESS)
150 rc = VINF_PGM_SYNC_CR3;
151 Log(("pgmGCGst32BitWriteHandlerCR3: detected conflict iPD1=%#x iPD2=%#x - returns %Rrc\n", iPD1, iPD2, rc));
152 return rc;
153 }
154 }
155
156 STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestCR3WriteHandled);
157 }
158 else
159 {
160 Assert(VBOX_FAILURE(rc));
161 if (rc == VERR_EM_INTERPRETER)
162 rc = VINF_EM_RAW_EMULATE_INSTR_PD_FAULT;
163 Log(("pgmGCGst32BitWriteHandlerCR3: returns %Rrc\n", rc));
164 STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestCR3WriteUnhandled);
165 }
166 return rc;
167}
168
169#endif /* PGM_TYPE_32BIT */
170
171
172#if PGM_GST_TYPE == PGM_TYPE_PAE
173
174/**
175 * Write access handler for the Guest CR3 page in PAE mode.
176 *
177 * This will try interpret the instruction, if failure fail back to the recompiler.
178 * Check if the changed PDEs are marked present and conflicts with our
179 * mappings. If conflict, we'll switch to the host context and resolve it there
180 *
181 * @returns VBox status code (appropritate for trap handling and GC return).
182 * @param pVM VM Handle.
183 * @param uErrorCode CPU Error code.
184 * @param pRegFrame Trap register frame.
185 * @param pvFault The fault address (cr2).
186 * @param GCPhysFault The GC physical address corresponding to pvFault.
187 * @param pvUser User argument.
188 */
189PGMGCDECL(int) pgmGCGstPAEWriteHandlerCR3(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser)
190{
191 AssertMsg(!pVM->pgm.s.fMappingsFixed, ("Shouldn't be registered when mappings are fixed!\n"));
192
193 /*
194 * Try interpret the instruction.
195 */
196 uint32_t cb;
197 int rc = EMInterpretInstruction(pVM, pRegFrame, pvFault, &cb);
198 if (VBOX_SUCCESS(rc) && cb)
199 {
200 /*
201 * Check if any of the PDs have changed.
202 * We'll simply check all of them instead of figuring out which one/two to check.
203 */
204 for (unsigned i = 0; i < 4; i++)
205 {
206 if ( CTXSUFF(pVM->pgm.s.pGstPaePDPTR)->a[i].n.u1Present
207 && ( CTXSUFF(pVM->pgm.s.pGstPaePDPTR)->a[i].u & X86_PDPE_PG_MASK)
208 != pVM->pgm.s.aGCPhysGstPaePDsMonitored[i])
209 {
210 /*
211 * The PDPE has changed.
212 * We will schedule a monitoring update for the next TLB Flush,
213 * InvalidatePage or SyncCR3.
214 *
215 * This isn't perfect, because a lazy page sync might be dealing with an half
216 * updated PDPE. However, we assume that the guest OS is disabling interrupts
217 * and being extremely careful (cmpxchg8b) when updating a PDPE where it's
218 * executing.
219 */
220 pVM->pgm.s.fSyncFlags |= PGM_SYNC_MONITOR_CR3;
221 Log(("pgmGCGstPaeWriteHandlerCR3: detected updated PDPE; [%d] = %#llx, Old GCPhys=%VGp\n",
222 i, CTXSUFF(pVM->pgm.s.pGstPaePDPTR)->a[i].u, pVM->pgm.s.aGCPhysGstPaePDsMonitored[i]));
223 }
224 }
225
226 STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestCR3WriteHandled);
227 }
228 else
229 {
230 Assert(VBOX_FAILURE(rc));
231 STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestCR3WriteUnhandled);
232 if (rc == VERR_EM_INTERPRETER)
233 rc = VINF_EM_RAW_EMULATE_INSTR_PD_FAULT;
234 }
235 Log(("pgmGCGstPaeWriteHandlerCR3: returns %Rrc\n", rc));
236 return rc;
237}
238
239
240/**
241 * Write access handler for the Guest PDs in PAE mode.
242 *
243 * This will try interpret the instruction, if failure fail back to the recompiler.
244 * Check if the changed PDEs are marked present and conflicts with our
245 * mappings. If conflict, we'll switch to the host context and resolve it there
246 *
247 * @returns VBox status code (appropritate for trap handling and GC return).
248 * @param pVM VM Handle.
249 * @param uErrorCode CPU Error code.
250 * @param pRegFrame Trap register frame.
251 * @param pvFault The fault address (cr2).
252 * @param GCPhysFault The GC physical address corresponding to pvFault.
253 * @param pvUser User argument.
254 */
255PGMGCDECL(int) pgmGCGstPAEWriteHandlerPD(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser)
256{
257 AssertMsg(!pVM->pgm.s.fMappingsFixed, ("Shouldn't be registered when mappings are fixed!\n"));
258
259 /*
260 * Try interpret the instruction.
261 */
262 uint32_t cb;
263 int rc = EMInterpretInstruction(pVM, pRegFrame, pvFault, &cb);
264 if (VBOX_SUCCESS(rc) && cb)
265 {
266 /*
267 * Figure out which of the 4 PDs this is.
268 */
269 RTGCUINTPTR i;
270 for (i = 0; i < 4; i++)
271 if (CTXSUFF(pVM->pgm.s.pGstPaePDPTR)->a[i].u == (GCPhysFault & X86_PTE_PAE_PG_MASK))
272 {
273 PX86PDPAE pPDSrc = pgmGstGetPaePD(&pVM->pgm.s, i << X86_PDPTR_SHIFT);
274 const RTGCUINTPTR offPD = GCPhysFault & PAGE_OFFSET_MASK;
275 const unsigned iPD1 = offPD / sizeof(X86PDEPAE);
276 const unsigned iPD2 = (offPD + cb - 1) / sizeof(X86PDEPAE);
277
278 Assert(cb > 0 && cb <= 8);
279 Assert(iPD1 < X86_PG_PAE_ENTRIES);
280 Assert(iPD2 < X86_PG_PAE_ENTRIES);
281
282#ifdef DEBUG
283 Log(("pgmGCGstPaeWriteHandlerPD: emulated change to i=%d iPD1=%#05x (%VGv)\n",
284 i, iPD1, (i << X86_PDPTR_SHIFT) | (iPD1 << X86_PD_PAE_SHIFT)));
285 if (iPD1 != iPD2)
286 Log(("pgmGCGstPaeWriteHandlerPD: emulated change to i=%d iPD2=%#05x (%VGv)\n",
287 i, iPD2, (i << X86_PDPTR_SHIFT) | (iPD2 << X86_PD_PAE_SHIFT)));
288#endif
289
290 if (!pVM->pgm.s.fMappingsFixed)
291 {
292 if ( ( pPDSrc->a[iPD1].n.u1Present
293 && pgmGetMapping(pVM, (RTGCPTR)((i << X86_PDPTR_SHIFT) | (iPD1 << X86_PD_PAE_SHIFT))) )
294 || ( iPD1 != iPD2
295 && pPDSrc->a[iPD2].n.u1Present
296 && pgmGetMapping(pVM, (RTGCPTR)((i << X86_PDPTR_SHIFT) | (iPD2 << X86_PD_PAE_SHIFT))) )
297 )
298 {
299 Log(("pgmGCGstPaeWriteHandlerPD: detected conflict iPD1=%#x iPD2=%#x\n", iPD1, iPD2));
300 STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestCR3WriteConflict);
301 VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
302 return VINF_PGM_SYNC_CR3;
303 }
304 }
305 break; /* ASSUMES no duplicate entries... */
306 }
307 Assert(i < 4);
308
309 STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestCR3WriteHandled);
310 }
311 else
312 {
313 Assert(VBOX_FAILURE(rc));
314 if (rc == VERR_EM_INTERPRETER)
315 rc = VINF_EM_RAW_EMULATE_INSTR_PD_FAULT;
316 else
317 Log(("pgmGCGst32BitWriteHandlerCR3: returns %Rrc\n", rc));
318 STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestCR3WriteUnhandled);
319 }
320 return rc;
321}
322
323#endif /* PGM_TYPE_PAE */
324
325
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