VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingProtect.c@ 60600

Last change on this file since 60600 was 60527, checked in by vboxsync, 9 years ago

bs3kit: Far updates.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.3 KB
Line 
1/* $Id: bs3-cmn-PagingProtect.c 60527 2016-04-18 09:11:04Z vboxsync $ */
2/** @file
3 * BS3Kit - Bs3PagingProtect
4 */
5
6/*
7 * Copyright (C) 2007-2016 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*********************************************************************************************************************************
28* Header Files *
29*********************************************************************************************************************************/
30#include "bs3kit-template-header.h"
31#include "bs3-cmn-paging.h"
32#include <iprt/asm-amd64-x86.h>
33#include <iprt/param.h>
34
35
36/*********************************************************************************************************************************
37* Defined Constants And Macros *
38*********************************************************************************************************************************/
39#if 0
40# define BS3PAGING_DPRINTF(a) Bs3TestPrintf a
41#else
42# define BS3PAGING_DPRINTF(a) do { } while (0)
43#endif
44
45
46static void *bs3PagingBuildPaeTable(uint64_t uTmpl, uint64_t cbIncrement, BS3MEMKIND enmKind, int *prc)
47{
48 uint64_t BS3_FAR *pau64 = (uint64_t BS3_FAR *)Bs3MemAlloc(enmKind, _4K);
49 if (pau64)
50 {
51 unsigned i;
52 for (i = 0; i < _4K / sizeof(uint64_t); i++, uTmpl += cbIncrement)
53 pau64[i] = uTmpl;
54 }
55 else
56 *prc = VERR_NO_MEMORY;
57 return pau64;
58}
59
60
61#undef bs3PagingGetLegacyPte
62BS3_CMN_DEF(X86PTE BS3_FAR *, bs3PagingGetLegacyPte,(RTCCUINTXREG cr3, uint32_t uFlat, bool fUseInvlPg, int *prc))
63{
64 X86PTE BS3_FAR *pPTE = NULL;
65#if TMPL_BITS == 16
66 uint32_t const uMaxAddr = BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode) ? _1M - 1 : BS3_SEL_TILED_AREA_SIZE - 1;
67#else
68 uint32_t const uMaxAddr = UINT32_MAX;
69#endif
70 BS3PAGING_DPRINTF(("bs3PagingGetLegacyPte: cr3=%RX32 uFlat=%RX32 uMaxAddr=%RX32\n", (uint32_t)cr3, uFlat, uMaxAddr));
71
72 *prc = VERR_OUT_OF_RANGE;
73 if (cr3 <= uMaxAddr)
74 {
75 unsigned const iPde = (uFlat >> X86_PD_SHIFT) & X86_PD_MASK;
76 PX86PD const pPD = (PX86PD)Bs3XptrFlatToCurrent(cr3 & X86_CR3_PAGE_MASK);
77
78 BS3_ASSERT(pPD->a[iPde].b.u1Present);
79 if (pPD->a[iPde].b.u1Present)
80 {
81 unsigned const iPte = (uFlat >> X86_PT_SHIFT) & X86_PT_MASK;
82
83 BS3_ASSERT(pPD->a[iPde].b.u1Present);
84 BS3PAGING_DPRINTF(("bs3PagingGetLegacyPte: pPD=%p iPde=%#x: %#RX32\n", pPD, iPde, pPD->a[iPde]));
85 if (pPD->a[iPde].b.u1Present)
86 {
87 if (!pPD->a[iPde].b.u1Size)
88 {
89 if (pPD->a[iPde].u <= uMaxAddr)
90 pPTE = &((X86PT BS3_FAR *)Bs3XptrFlatToCurrent(pPD->a[iPde].u & ~(uint32_t)PAGE_OFFSET_MASK))->a[iPte];
91 }
92 else
93 {
94 X86PT BS3_FAR *pPT;
95 uint32_t uPte = (pPD->a[iPde].u & ~(uint32_t)(X86_PTE_PG_MASK | X86_PDE4M_PS | X86_PDE4M_G)) | X86_PTE_D;
96 if (pPD->a[iPde].b.u1Global)
97 uPte |= X86_PTE_G;
98 if (pPD->a[iPde].b.u1PAT)
99 uPte |= X86_PTE_PAT;
100
101 pPT = (X86PT BS3_FAR *)bs3PagingBuildPaeTable(RT_MAKE_U64(uPte, uPte + PAGE_SIZE),
102 RT_MAKE_U64(PAGE_SIZE*2, PAGE_SIZE*2),
103 uMaxAddr > _1M ? BS3MEMKIND_TILED : BS3MEMKIND_REAL, prc);
104
105 BS3PAGING_DPRINTF(("bs3PagingGetLegacyPte: Built pPT=%p uPte=%RX32\n", pPT, uPte));
106 if (pPT)
107 {
108 pPD->a[iPde].u = Bs3SelPtrToFlat(pPT)
109 | (pPD->a[iPde].u & ~(uint32_t)(X86_PTE_PG_MASK | X86_PDE4M_PS | X86_PDE4M_G | X86_PDE4M_D));
110 BS3PAGING_DPRINTF(("bs3PagingGetLegacyPte: iPde=%#x: %#RX32\n", iPde, pPD->a[iPde].u));
111 if (fUseInvlPg)
112 ASMInvalidatePage(uFlat);
113 pPTE = &pPT->a[iPte];
114 }
115 }
116 }
117 }
118 }
119 return pPTE;
120}
121
122
123#undef bs3PagingGetPte
124BS3_CMN_DEF(X86PTEPAE BS3_FAR *, bs3PagingGetPte,(RTCCUINTXREG cr3, uint64_t uFlat, bool fUseInvlPg, int *prc))
125{
126 X86PTEPAE BS3_FAR *pPTE = NULL;
127#if TMPL_BITS == 16
128 uint32_t const uMaxAddr = BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode) ? _1M - 1 : BS3_SEL_TILED_AREA_SIZE - 1;
129#else
130 uintptr_t const uMaxAddr = ~(uintptr_t)0;
131#endif
132
133 *prc = VERR_OUT_OF_RANGE;
134 if ((cr3 & X86_CR3_AMD64_PAGE_MASK) <= uMaxAddr)
135 {
136 X86PDPAE BS3_FAR *pPD;
137 if (BS3_MODE_IS_64BIT_SYS(g_bBs3CurrentMode))
138 {
139 unsigned const iPml4e = (uFlat >> X86_PML4_SHIFT) & X86_PML4_MASK;
140 X86PML4 BS3_FAR *pPml4 = (X86PML4 BS3_FAR *)Bs3XptrFlatToCurrent(cr3 & X86_CR3_AMD64_PAGE_MASK);
141 BS3_ASSERT(pPml4->a[iPml4e].n.u1Present);
142 if ((pPml4->a[iPml4e].u & X86_PML4E_PG_MASK) <= uMaxAddr)
143 {
144 unsigned const iPdpte = (uFlat >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
145 X86PDPT BS3_FAR *pPdpt = (X86PDPT BS3_FAR *)Bs3XptrFlatToCurrent(pPml4->a[iPml4e].u & X86_PML4E_PG_MASK);
146 BS3_ASSERT(pPdpt->a[iPdpte].n.u1Present);
147 if (!pPdpt->a[iPdpte].b.u1Size)
148 {
149 if ((pPdpt->a[iPdpte].u & X86_PDPE_PG_MASK) <= uMaxAddr)
150 pPD = (X86PDPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPdpt->a[iPdpte].u & ~(uint64_t)PAGE_OFFSET_MASK);
151 }
152 else
153 {
154 /* Split 1GB page. */
155 pPD = (X86PDPAE BS3_FAR *)bs3PagingBuildPaeTable(pPdpt->a[iPdpte].u, _2M,
156 uMaxAddr > _1M ? BS3MEMKIND_TILED : BS3MEMKIND_REAL, prc);
157 if (pPD)
158 {
159 pPdpt->a[iPdpte].u = Bs3SelPtrToFlat(pPD)
160 | ( pPdpt->a[iPdpte].u
161 & ~(uint64_t)(X86_PDPE_PG_MASK | X86_PDE4M_PS | X86_PDE4M_G | X86_PDE4M_D));
162 if (fUseInvlPg)
163 ASMInvalidatePage(uFlat);
164 }
165 }
166 }
167 }
168 //else if (uFlat <= UINT32_MAX) - fixme!
169 else if (!(uFlat >> 32))
170 {
171 unsigned const iPdpte = ((uint32_t)uFlat >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
172 X86PDPT BS3_FAR *pPdpt = (X86PDPT BS3_FAR *)Bs3XptrFlatToCurrent(cr3 & X86_CR3_PAE_PAGE_MASK);
173 BS3_ASSERT(pPdpt->a[iPdpte].n.u1Present);
174 if ((pPdpt->a[iPdpte].u & X86_PDPE_PG_MASK) <= uMaxAddr)
175 pPD = (X86PDPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPdpt->a[iPdpte].u & X86_PDPE_PG_MASK);
176 }
177 else
178 pPD = NULL;
179 if (pPD)
180 {
181 unsigned const iPte = (uFlat >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK;
182 unsigned const iPde = (uFlat >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
183 if (!pPD->a[iPde].b.u1Size)
184 {
185 if ((pPD->a[iPde].u & X86_PDE_PAE_PG_MASK) <= uMaxAddr)
186 pPTE = &((X86PTPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPD->a[iPde].u & ~(uint64_t)PAGE_OFFSET_MASK))->a[iPte];
187 }
188 else
189 {
190 /* Split 2MB page. */
191 X86PTPAE BS3_FAR *pPT;
192 uint64_t uTmpl = pPD->a[iPde].u & ~(uint64_t)(X86_PDE4M_G | X86_PDE4M_PS | X86_PDE4M_PAT);
193 if (!pPD->a[iPde].b.u1Global)
194 uTmpl |= X86_PTE_G;
195 if (!pPD->a[iPde].b.u1PAT)
196 uTmpl |= X86_PTE_PAT;
197
198 pPT = (X86PTPAE BS3_FAR *)bs3PagingBuildPaeTable(uTmpl, PAGE_SIZE,
199 uMaxAddr > _1M ? BS3MEMKIND_TILED : BS3MEMKIND_REAL, prc);
200 if (pPT)
201 {
202 pPD->a[iPde].u = Bs3SelPtrToFlat(pPT)
203 | (pPD->a[iPde].u & ~(uint64_t)(X86_PTE_PAE_PG_MASK | X86_PDE4M_PS | X86_PDE4M_G | X86_PDE4M_D));
204 if (fUseInvlPg)
205 ASMInvalidatePage(uFlat);
206 pPTE = &pPT->a[iPte];
207 }
208 }
209 }
210 }
211
212 return pPTE;
213}
214
215
216#undef Bs3PagingProtect
217BS3_CMN_DEF(int, Bs3PagingProtect,(uint64_t uFlat, uint64_t cb, uint64_t fSet, uint64_t fClear))
218{
219 RTCCUINTXREG const cr3 = ASMGetCR3();
220 RTCCUINTXREG const cr4 = g_uBs3CpuDetected & BS3CPU_F_CPUID ? ASMGetCR4() : 0;
221 bool const fLegacyPTs = !(cr4 & X86_CR4_PAE);
222 bool const fUseInvlPg = (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80486
223 && ( cb < UINT64_C(16)*PAGE_SIZE
224 || (cr4 & X86_CR4_PGE));
225 unsigned cEntries;
226 int rc;
227
228 /*
229 * Adjust the range parameters.
230 */
231 cb += uFlat & PAGE_OFFSET_MASK;
232 cb = RT_ALIGN_64(cb, PAGE_SIZE);
233 uFlat &= ~(uint64_t)PAGE_OFFSET_MASK;
234
235 fSet &= ~X86_PTE_PAE_PG_MASK;
236 fClear &= ~X86_PTE_PAE_PG_MASK;
237
238 BS3PAGING_DPRINTF(("Bs3PagingProtect: uFlat=%RX64 cb=%RX64 fSet=%RX64 fClear=%RX64 %s %s\n", uFlat, cb, fSet, fClear,
239 fLegacyPTs ? "legacy" : "pae/amd64", fUseInvlPg ? "invlpg" : "reload-cr3"));
240 if (fLegacyPTs)
241 {
242 /*
243 * Legacy page tables.
244 */
245 while ((uint32_t)cb > 0)
246 {
247 PX86PTE pPte = BS3_CMN_NM(bs3PagingGetLegacyPte)(cr3, (uint32_t)uFlat, fUseInvlPg, &rc);
248 if (!pPte)
249 return rc;
250
251 cEntries = X86_PG_ENTRIES - ((uFlat >> X86_PT_SHIFT) & X86_PT_MASK);
252 while (cEntries-- > 0 && cb > 0)
253 {
254 pPte->u &= ~(uint32_t)fClear;
255 pPte->u |= (uint32_t)fSet;
256 if (fUseInvlPg)
257 ASMInvalidatePage(uFlat);
258
259 pPte++;
260 uFlat += PAGE_SIZE;
261 cb -= PAGE_SIZE;
262 }
263 }
264 }
265 else
266 {
267 /*
268 * Long mode or PAE page tables (at this level they are the same).
269 */
270 while (cb > 0)
271 {
272 PX86PTEPAE pPte = BS3_CMN_NM(bs3PagingGetPte)(cr3, uFlat, fUseInvlPg, &rc);
273 if (!pPte)
274 return rc;
275
276 cEntries = X86_PG_ENTRIES - ((uFlat >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK);
277 while (cEntries-- > 0 && cb > 0)
278 {
279 pPte->u &= ~fClear;
280 pPte->u |= fSet;
281 if (fUseInvlPg)
282 ASMInvalidatePage(uFlat);
283
284 pPte++;
285 uFlat += PAGE_SIZE;
286 cb -= PAGE_SIZE;
287 }
288 }
289 }
290
291 /*
292 * Flush the TLB if we didn't use INVLPG above.
293 */
294 BS3PAGING_DPRINTF(("Bs3PagingProtect: reloading cr3=%RX32\n", (uint32_t)cr3));
295 //if (!fUseInvlPg)
296 ASMSetCR3(cr3);
297 BS3PAGING_DPRINTF(("Bs3PagingProtect: reloaded cr3=%RX32\n", (uint32_t)cr3));
298
299 return VINF_SUCCESS;
300}
301
302
303#undef Bs3PagingProtectPtr
304BS3_CMN_DEF(int, Bs3PagingProtectPtr,(void *pv, size_t cb, uint64_t fSet, uint64_t fClear))
305{
306#if ARCH_BITS == 16
307 return BS3_CMN_NM(Bs3PagingProtect)(Bs3SelPtrToFlat(pv), cb, fSet, fClear);
308#else
309 return BS3_CMN_NM(Bs3PagingProtect)((uintptr_t)pv, cb, fSet, fClear);
310#endif
311}
312
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