VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/PGMAllMap.cpp@ 13126

Last change on this file since 13126 was 13019, checked in by vboxsync, 16 years ago

#1865: PGM ...

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.3 KB
Line 
1/* $Id: PGMAllMap.cpp 13019 2008-10-06 16:21:01Z vboxsync $ */
2/** @file
3 * PGM - Page Manager and Monitor - All context code.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#define LOG_GROUP LOG_GROUP_PGM
26#include <VBox/pgm.h>
27#include "PGMInternal.h"
28#include <VBox/vm.h>
29#include <iprt/assert.h>
30#include <iprt/asm.h>
31#include <VBox/err.h>
32
33
34/**
35 * Maps a range of physical pages at a given virtual address
36 * in the guest context.
37 *
38 * The GC virtual address range must be within an existing mapping.
39 *
40 * @returns VBox status code.
41 * @param pVM The virtual machine.
42 * @param GCPtr Where to map the page(s). Must be page aligned.
43 * @param HCPhys Start of the range of physical pages. Must be page aligned.
44 * @param cbPages Number of bytes to map. Must be page aligned.
45 * @param fFlags Page flags (X86_PTE_*).
46 */
47VMMDECL(int) PGMMap(PVM pVM, RTGCUINTPTR GCPtr, RTHCPHYS HCPhys, uint32_t cbPages, unsigned fFlags)
48{
49 AssertMsg(pVM->pgm.s.offVM, ("Bad init order\n"));
50
51 /*
52 * Validate input.
53 */
54 AssertMsg(RT_ALIGN_T(GCPtr, PAGE_SIZE, RTGCUINTPTR) == GCPtr, ("Invalid alignment GCPtr=%#x\n", GCPtr));
55 AssertMsg(cbPages > 0 && RT_ALIGN_32(cbPages, PAGE_SIZE) == cbPages, ("Invalid cbPages=%#x\n", cbPages));
56 AssertMsg(!(fFlags & X86_PDE_PG_MASK), ("Invalid flags %#x\n", fFlags));
57 //Assert(HCPhys < _4G); --- Don't *EVER* try 32-bit shadow mode on a PAE/AMD64 box with memory above 4G !!!
58
59 /* hypervisor defaults */
60 if (!fFlags)
61 fFlags = X86_PTE_P | X86_PTE_A | X86_PTE_D;
62
63 /*
64 * Find the mapping.
65 */
66 PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings);
67 while (pCur)
68 {
69 if (GCPtr - pCur->GCPtr < pCur->cb)
70 {
71 if (GCPtr + cbPages - 1 > pCur->GCPtrLast)
72 {
73 AssertMsgFailed(("Invalid range!!\n"));
74 return VERR_INVALID_PARAMETER;
75 }
76
77 /*
78 * Setup PTE.
79 */
80 X86PTEPAE Pte;
81 Pte.u = fFlags | (HCPhys & X86_PTE_PAE_PG_MASK);
82
83 /*
84 * Update the page tables.
85 */
86 for (;;)
87 {
88 RTGCUINTPTR off = GCPtr - pCur->GCPtr;
89 const unsigned iPT = off >> X86_PD_SHIFT;
90 const unsigned iPageNo = (off >> PAGE_SHIFT) & X86_PT_MASK;
91
92 /* 32-bit */
93 pCur->aPTs[iPT].CTX_SUFF(pPT)->a[iPageNo].u = (uint32_t)Pte.u; /* ASSUMES HCPhys < 4GB and/or that we're never gonna do 32-bit on a PAE host! */
94
95 /* pae */
96 pCur->aPTs[iPT].CTX_SUFF(paPaePTs)[iPageNo / 512].a[iPageNo % 512].u = Pte.u;
97
98 /* next */
99 cbPages -= PAGE_SIZE;
100 if (!cbPages)
101 break;
102 GCPtr += PAGE_SIZE;
103 Pte.u += PAGE_SIZE;
104 }
105
106 return VINF_SUCCESS;
107 }
108
109 /* next */
110 pCur = pCur->CTX_SUFF(pNext);
111 }
112
113 AssertMsgFailed(("GCPtr=%#x was not found in any mapping ranges!\n", GCPtr));
114 return VERR_INVALID_PARAMETER;
115}
116
117
118/**
119 * Sets (replaces) the page flags for a range of pages in a mapping.
120 *
121 * @returns VBox status.
122 * @param pVM VM handle.
123 * @param GCPtr Virtual address of the first page in the range.
124 * @param cb Size (in bytes) of the range to apply the modification to.
125 * @param fFlags Page flags X86_PTE_*, excluding the page mask of course.
126 */
127VMMDECL(int) PGMMapSetPage(PVM pVM, RTGCPTR GCPtr, uint64_t cb, uint64_t fFlags)
128{
129 return PGMMapModifyPage(pVM, GCPtr, cb, fFlags, 0);
130}
131
132
133/**
134 * Modify page flags for a range of pages in a mapping.
135 *
136 * The existing flags are ANDed with the fMask and ORed with the fFlags.
137 *
138 * @returns VBox status code.
139 * @param pVM VM handle.
140 * @param GCPtr Virtual address of the first page in the range.
141 * @param cb Size (in bytes) of the range to apply the modification to.
142 * @param fFlags The OR mask - page flags X86_PTE_*, excluding the page mask of course.
143 * @param fMask The AND mask - page flags X86_PTE_*, excluding the page mask of course.
144 */
145VMMDECL(int) PGMMapModifyPage(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
146{
147 /*
148 * Validate input.
149 */
150 if (fFlags & X86_PTE_PAE_PG_MASK)
151 {
152 AssertMsgFailed(("fFlags=%#x\n", fFlags));
153 return VERR_INVALID_PARAMETER;
154 }
155 if (!cb)
156 {
157 AssertFailed();
158 return VERR_INVALID_PARAMETER;
159 }
160
161 /*
162 * Align the input.
163 */
164 cb += (RTGCUINTPTR)GCPtr & PAGE_OFFSET_MASK;
165 cb = RT_ALIGN_Z(cb, PAGE_SIZE);
166 GCPtr = (RTGCPTR)((RTGCUINTPTR)GCPtr & PAGE_BASE_GC_MASK);
167
168 /*
169 * Find the mapping.
170 */
171 PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings);
172 while (pCur)
173 {
174 RTGCUINTPTR off = (RTGCUINTPTR)GCPtr - (RTGCUINTPTR)pCur->GCPtr;
175 if (off < pCur->cb)
176 {
177 if (off + cb > pCur->cb)
178 {
179 AssertMsgFailed(("Invalid page range %#x LB%#x. mapping '%s' %#x to %#x\n",
180 GCPtr, cb, pCur->pszDesc, pCur->GCPtr, pCur->GCPtrLast));
181 return VERR_INVALID_PARAMETER;
182 }
183
184 /*
185 * Perform the requested operation.
186 */
187 while (cb > 0)
188 {
189 unsigned iPT = off >> X86_PD_SHIFT;
190 unsigned iPTE = (off >> PAGE_SHIFT) & X86_PT_MASK;
191 while (cb > 0 && iPTE < RT_ELEMENTS(pCur->aPTs[iPT].CTX_SUFF(pPT)->a))
192 {
193 /* 32-Bit */
194 pCur->aPTs[iPT].CTX_SUFF(pPT)->a[iPTE].u &= fMask | X86_PTE_PG_MASK;
195 pCur->aPTs[iPT].CTX_SUFF(pPT)->a[iPTE].u |= fFlags & ~X86_PTE_PG_MASK;
196
197 /* PAE */
198 pCur->aPTs[iPT].CTX_SUFF(paPaePTs)[iPTE / 512].a[iPTE % 512].u &= fMask | X86_PTE_PAE_PG_MASK;
199 pCur->aPTs[iPT].CTX_SUFF(paPaePTs)[iPTE / 512].a[iPTE % 512].u |= fFlags & ~X86_PTE_PAE_PG_MASK;
200
201 /* invalidate tls */
202 PGM_INVL_PG((RTGCUINTPTR)pCur->GCPtr + off);
203
204 /* next */
205 iPTE++;
206 cb -= PAGE_SIZE;
207 off += PAGE_SIZE;
208 }
209 }
210
211 return VINF_SUCCESS;
212 }
213 /* next */
214 pCur = pCur->CTX_SUFF(pNext);
215 }
216
217 AssertMsgFailed(("Page range %#x LB%#x not found\n", GCPtr, cb));
218 return VERR_INVALID_PARAMETER;
219}
220
221
222
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