VirtualBox

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

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

bs3kit: 386 fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.2 KB
Line 
1/* $Id: bs3-cmn-PagingProtect.c 60321 2016-04-05 00:33:14Z 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
61BS3_DECL(X86PTE BS3_FAR *) bs3PagingGetLegacyPte(RTCCUINTXREG cr3, uint32_t uFlat, bool fUseInvlPg, int *prc)
62{
63 X86PTE BS3_FAR *pPTE = NULL;
64#if TMPL_BITS == 16
65 uint32_t const uMaxAddr = BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode) ? _1M - 1 : BS3_SEL_TILED_AREA_SIZE - 1;
66#else
67 uint32_t const uMaxAddr = UINT32_MAX;
68#endif
69 BS3PAGING_DPRINTF(("bs3PagingGetLegacyPte: cr3=%RX32 uFlat=%RX32 uMaxAddr=%RX32\n", (uint32_t)cr3, uFlat, uMaxAddr));
70
71 *prc = VERR_OUT_OF_RANGE;
72 if (cr3 <= uMaxAddr)
73 {
74 unsigned const iPde = (uFlat >> X86_PD_SHIFT) & X86_PD_MASK;
75 PX86PD const pPD = (PX86PD)Bs3XptrFlatToCurrent(cr3 & X86_CR3_PAGE_MASK);
76
77 BS3_ASSERT(pPD->a[iPde].b.u1Present);
78 if (pPD->a[iPde].b.u1Present)
79 {
80 unsigned const iPte = (uFlat >> X86_PT_SHIFT) & X86_PT_MASK;
81
82 BS3_ASSERT(pPD->a[iPde].b.u1Present);
83 BS3PAGING_DPRINTF(("bs3PagingGetLegacyPte: pPD=%p iPde=%#x: %#RX32\n", pPD, iPde, pPD->a[iPde]));
84 if (pPD->a[iPde].b.u1Present)
85 {
86 if (!pPD->a[iPde].b.u1Size)
87 {
88 if (pPD->a[iPde].u <= uMaxAddr)
89 pPTE = &((X86PT BS3_FAR *)Bs3XptrFlatToCurrent(pPD->a[iPde].u & ~(uint32_t)PAGE_OFFSET_MASK))->a[iPte];
90 }
91 else
92 {
93 X86PT BS3_FAR *pPT;
94 uint32_t uPte = (pPD->a[iPde].u & ~(uint32_t)(X86_PTE_PG_MASK | X86_PDE4M_PS | X86_PDE4M_G)) | X86_PTE_D;
95 if (pPD->a[iPde].b.u1Global)
96 uPte |= X86_PTE_G;
97 if (pPD->a[iPde].b.u1PAT)
98 uPte |= X86_PTE_PAT;
99
100 pPT = (X86PT BS3_FAR *)bs3PagingBuildPaeTable(RT_MAKE_U64(uPte, uPte + PAGE_SIZE),
101 RT_MAKE_U64(PAGE_SIZE*2, PAGE_SIZE*2),
102 uMaxAddr > _1M ? BS3MEMKIND_TILED : BS3MEMKIND_REAL, prc);
103
104 BS3PAGING_DPRINTF(("bs3PagingGetLegacyPte: Built pPT=%p uPte=%RX32\n", pPT, uPte));
105 if (pPT)
106 {
107 pPD->a[iPde].u = Bs3SelPtrToFlat(pPT)
108 | (pPD->a[iPde].u & ~(uint32_t)(X86_PTE_PG_MASK | X86_PDE4M_PS | X86_PDE4M_G | X86_PDE4M_D));
109 BS3PAGING_DPRINTF(("bs3PagingGetLegacyPte: iPde=%#x: %#RX32\n", iPde, pPD->a[iPde].u));
110 if (fUseInvlPg)
111 ASMInvalidatePage(uFlat);
112 pPTE = &pPT->a[iPte];
113 }
114 }
115 }
116 }
117 }
118 return pPTE;
119}
120
121
122BS3_DECL(X86PTEPAE BS3_FAR *) bs3PagingGetPte(RTCCUINTXREG cr3, uint64_t uFlat, bool fUseInvlPg, int *prc)
123{
124 X86PTEPAE BS3_FAR *pPTE = NULL;
125#if TMPL_BITS == 16
126 uint32_t const uMaxAddr = BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode) ? _1M - 1 : BS3_SEL_TILED_AREA_SIZE - 1;
127#else
128 uintptr_t const uMaxAddr = ~(uintptr_t)0;
129#endif
130
131 *prc = VERR_OUT_OF_RANGE;
132 if ((cr3 & X86_CR3_AMD64_PAGE_MASK) <= uMaxAddr)
133 {
134 X86PDPAE BS3_FAR *pPD;
135 if (BS3_MODE_IS_64BIT_SYS(g_bBs3CurrentMode))
136 {
137 unsigned const iPml4e = (uFlat >> X86_PML4_SHIFT) & X86_PML4_MASK;
138 X86PML4 BS3_FAR *pPml4 = (X86PML4 BS3_FAR *)Bs3XptrFlatToCurrent(cr3 & X86_CR3_AMD64_PAGE_MASK);
139 BS3_ASSERT(pPml4->a[iPml4e].n.u1Present);
140 if ((pPml4->a[iPml4e].u & X86_PML4E_PG_MASK) <= uMaxAddr)
141 {
142 unsigned const iPdpte = (uFlat >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
143 X86PDPT BS3_FAR *pPdpt = (X86PDPT BS3_FAR *)Bs3XptrFlatToCurrent(pPml4->a[iPml4e].u & X86_PML4E_PG_MASK);
144 BS3_ASSERT(pPdpt->a[iPdpte].n.u1Present);
145 if (!pPdpt->a[iPdpte].b.u1Size)
146 {
147 if ((pPdpt->a[iPdpte].u & X86_PDPE_PG_MASK) <= uMaxAddr)
148 pPD = (X86PDPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPdpt->a[iPdpte].u & ~(uint64_t)PAGE_OFFSET_MASK);
149 }
150 else
151 {
152 /* Split 1GB page. */
153 pPD = (X86PDPAE BS3_FAR *)bs3PagingBuildPaeTable(pPdpt->a[iPdpte].u, _2M,
154 uMaxAddr > _1M ? BS3MEMKIND_TILED : BS3MEMKIND_REAL, prc);
155 if (pPD)
156 {
157 pPdpt->a[iPdpte].u = Bs3SelPtrToFlat(pPD)
158 | ( pPdpt->a[iPdpte].u
159 & ~(uint64_t)(X86_PDPE_PG_MASK | X86_PDE4M_PS | X86_PDE4M_G | X86_PDE4M_D));
160 if (fUseInvlPg)
161 ASMInvalidatePage(uFlat);
162 }
163 }
164 }
165 }
166 //else if (uFlat <= UINT32_MAX) - fixme!
167 else if (!(uFlat >> 32))
168 {
169 unsigned const iPdpte = ((uint32_t)uFlat >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
170 X86PDPT BS3_FAR *pPdpt = (X86PDPT BS3_FAR *)Bs3XptrFlatToCurrent(cr3 & X86_CR3_PAE_PAGE_MASK);
171 BS3_ASSERT(pPdpt->a[iPdpte].n.u1Present);
172 if ((pPdpt->a[iPdpte].u & X86_PDPE_PG_MASK) <= uMaxAddr)
173 pPD = (X86PDPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPdpt->a[iPdpte].u & X86_PDPE_PG_MASK);
174 }
175 else
176 pPD = NULL;
177 if (pPD)
178 {
179 unsigned const iPte = (uFlat >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK;
180 unsigned const iPde = (uFlat >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
181 if (!pPD->a[iPde].b.u1Size)
182 {
183 if ((pPD->a[iPde].u & X86_PDE_PAE_PG_MASK) <= uMaxAddr)
184 pPTE = &((X86PTPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPD->a[iPde].u & ~(uint64_t)PAGE_OFFSET_MASK))->a[iPte];
185 }
186 else
187 {
188 /* Split 2MB page. */
189 X86PTPAE BS3_FAR *pPT;
190 uint64_t uTmpl = pPD->a[iPde].u & ~(uint64_t)(X86_PDE4M_G | X86_PDE4M_PS | X86_PDE4M_PAT);
191 if (!pPD->a[iPde].b.u1Global)
192 uTmpl |= X86_PTE_G;
193 if (!pPD->a[iPde].b.u1PAT)
194 uTmpl |= X86_PTE_PAT;
195
196 pPT = (X86PTPAE BS3_FAR *)bs3PagingBuildPaeTable(uTmpl, PAGE_SIZE,
197 uMaxAddr > _1M ? BS3MEMKIND_TILED : BS3MEMKIND_REAL, prc);
198 if (pPT)
199 {
200 pPD->a[iPde].u = Bs3SelPtrToFlat(pPT)
201 | (pPD->a[iPde].u & ~(uint64_t)(X86_PTE_PAE_PG_MASK | X86_PDE4M_PS | X86_PDE4M_G | X86_PDE4M_D));
202 if (fUseInvlPg)
203 ASMInvalidatePage(uFlat);
204 pPTE = &pPT->a[iPte];
205 }
206 }
207 }
208 }
209
210 return pPTE;
211}
212
213
214BS3_DECL(int) Bs3PagingProtect(uint64_t uFlat, uint64_t cb, uint64_t fSet, uint64_t fClear)
215{
216 RTCCUINTXREG const cr3 = ASMGetCR3();
217 RTCCUINTXREG const cr4 = g_uBs3CpuDetected & BS3CPU_F_CPUID ? ASMGetCR4() : 0;
218 bool const fLegacyPTs = !(cr4 & X86_CR4_PAE);
219 bool const fUseInvlPg = (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80486
220 && ( cb < UINT64_C(16)*PAGE_SIZE
221 || (cr4 & X86_CR4_PGE));
222 unsigned cEntries;
223 int rc;
224
225 /*
226 * Adjust the range parameters.
227 */
228 cb += uFlat & PAGE_OFFSET_MASK;
229 cb = RT_ALIGN_64(cb, PAGE_SIZE);
230 uFlat &= ~(uint64_t)PAGE_OFFSET_MASK;
231
232 fSet &= ~X86_PTE_PAE_PG_MASK;
233 fClear &= ~X86_PTE_PAE_PG_MASK;
234
235 BS3PAGING_DPRINTF(("Bs3PagingProtect: uFlat=%RX64 cb=%RX64 fSet=%RX64 fClear=%RX64 %s %s\n", uFlat, cb, fSet, fClear,
236 fLegacyPTs ? "legacy" : "pae/amd64", fUseInvlPg ? "invlpg" : "reload-cr3"));
237 if (fLegacyPTs)
238 {
239 /*
240 * Legacy page tables.
241 */
242 while ((uint32_t)cb > 0)
243 {
244 PX86PTE pPte = bs3PagingGetLegacyPte(cr3, (uint32_t)uFlat, fUseInvlPg, &rc);
245 if (!pPte)
246 return rc;
247
248 cEntries = X86_PG_ENTRIES - ((uFlat >> X86_PT_SHIFT) & X86_PT_MASK);
249 while (cEntries-- > 0 && cb > 0)
250 {
251 pPte->u &= ~(uint32_t)fClear;
252 pPte->u |= (uint32_t)fSet;
253 if (fUseInvlPg)
254 ASMInvalidatePage(uFlat);
255
256 pPte++;
257 uFlat += PAGE_SIZE;
258 cb -= PAGE_SIZE;
259 }
260 }
261 }
262 else
263 {
264 /*
265 * Long mode or PAE page tables (at this level they are the same).
266 */
267 while (cb > 0)
268 {
269 PX86PTEPAE pPte = bs3PagingGetPte(cr3, uFlat, fUseInvlPg, &rc);
270 if (!pPte)
271 return rc;
272
273 cEntries = X86_PG_ENTRIES - ((uFlat >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK);
274 while (cEntries-- > 0 && cb > 0)
275 {
276 pPte->u &= ~fClear;
277 pPte->u |= fSet;
278 if (fUseInvlPg)
279 ASMInvalidatePage(uFlat);
280
281 pPte++;
282 uFlat += PAGE_SIZE;
283 cb -= PAGE_SIZE;
284 }
285 }
286 }
287
288 /*
289 * Flush the TLB if we didn't use INVLPG above.
290 */
291 BS3PAGING_DPRINTF(("Bs3PagingProtect: reloading cr3=%RX32\n", (uint32_t)cr3));
292 //if (!fUseInvlPg)
293 ASMSetCR3(cr3);
294 BS3PAGING_DPRINTF(("Bs3PagingProtect: reloaded cr3=%RX32\n", (uint32_t)cr3));
295
296 return VINF_SUCCESS;
297}
298
299
300BS3_DECL(int) Bs3PagingProtectPtr(void *pv, size_t cb, uint64_t fSet, uint64_t fClear)
301{
302#if ARCH_BITS == 16
303 return Bs3PagingProtect(Bs3SelPtrToFlat(pv), cb, fSet, fClear);
304#else
305 return Bs3PagingProtect((uintptr_t)pv, cb, fSet, fClear);
306#endif
307}
308
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