VirtualBox

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

Last change on this file since 8110 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

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