VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/PGMR0.cpp@ 17522

Last change on this file since 17522 was 17421, checked in by vboxsync, 16 years ago

PGM,VMM,GMM: handy page allocation and some other fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.8 KB
Line 
1/* $Id: PGMR0.cpp 17421 2009-03-05 20:17:00Z vboxsync $ */
2/** @file
3 * PGM - Page Manager and Monitor, Ring-0.
4 */
5
6/*
7 * Copyright (C) 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 <VBox/log.h>
30#include <VBox/err.h>
31#include <iprt/assert.h>
32
33__BEGIN_DECLS
34#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_PROT(name)
35#include "PGMR0Bth.h"
36#undef PGM_BTH_NAME
37
38#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_PROT(name)
39#include "PGMR0Bth.h"
40#undef PGM_BTH_NAME
41
42#define PGM_BTH_NAME(name) PGM_BTH_NAME_AMD64_PROT(name)
43#include "PGMR0Bth.h"
44#undef PGM_BTH_NAME
45
46#define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_PROT(name)
47#include "PGMR0Bth.h"
48#undef PGM_BTH_NAME
49
50__END_DECLS
51
52
53/**
54 * Worker function for PGMR3PhysAllocateHandyPages and pgmPhysEnsureHandyPage.
55 *
56 * @returns The following VBox status codes.
57 * @retval VINF_SUCCESS on success. FF cleared.
58 * @retval VINF_EM_NO_MEMORY if we're out of memory. The FF is set in this case.
59 *
60 * @param pVM The VM handle.
61 *
62 * @remarks Must be called from within the PGM critical section. The caller
63 * must clear the new pages.
64 */
65VMMR0DECL(int) PGMR0PhysAllocateHandyPages(PVM pVM)
66{
67 Assert(PDMCritSectIsOwner(&pVM->pgm.s.CritSect));
68
69 uint32_t iFirst = pVM->pgm.s.cHandyPages;
70 AssertMsgReturn(iFirst <= RT_ELEMENTS(pVM->pgm.s.aHandyPages), ("%d", iFirst), VERR_INTERNAL_ERROR);
71 uint32_t cPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages) - iFirst;
72 if (!cPages)
73 return VINF_SUCCESS;
74
75 int rc = GMMR0AllocateHandyPages(pVM, cPages, cPages, &pVM->pgm.s.aHandyPages[iFirst]);
76 if (RT_SUCCESS(rc))
77 {
78 for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
79 {
80 Assert(pVM->pgm.s.aHandyPages[i].idPage != NIL_GMM_PAGEID);
81 Assert(pVM->pgm.s.aHandyPages[i].idPage <= GMM_PAGEID_LAST);
82 Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID);
83 Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys != NIL_RTHCPHYS);
84 Assert(!(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys & ~X86_PTE_PAE_PG_MASK));
85 }
86
87 pVM->pgm.s.cHandyPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages);
88 }
89 LogFlow(("PGMR0PhysAllocateHandyPages: cPages=%d rc=%Rrc\n", cPages, rc));
90 return rc;
91}
92
93
94/**
95 * #PF Handler for nested paging.
96 *
97 * @returns VBox status code (appropriate for trap handling and GC return).
98 * @param pVM VM Handle.
99 * @param enmShwPagingMode Paging mode for the nested page tables
100 * @param uErr The trap error code.
101 * @param pRegFrame Trap register frame.
102 * @param pvFault The fault address.
103 */
104VMMR0DECL(int) PGMR0Trap0eHandlerNestedPaging(PVM pVM, PGMMODE enmShwPagingMode, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPHYS pvFault)
105{
106 int rc;
107
108 LogFlow(("PGMTrap0eHandler: uErr=%#x pvFault=%RGp eip=%RGv\n", uErr, pvFault, (RTGCPTR)pRegFrame->rip));
109 STAM_PROFILE_START(&pVM->pgm.s.StatRZTrap0e, a);
110 STAM_STATS({ pVM->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = NULL; } );
111
112 /* AMD uses the host's paging mode; Intel has a single mode (EPT). */
113 AssertMsg(enmShwPagingMode == PGMMODE_32_BIT || enmShwPagingMode == PGMMODE_PAE || enmShwPagingMode == PGMMODE_PAE_NX || enmShwPagingMode == PGMMODE_AMD64 || enmShwPagingMode == PGMMODE_AMD64_NX || enmShwPagingMode == PGMMODE_EPT, ("enmShwPagingMode=%d\n", enmShwPagingMode));
114
115#ifdef VBOX_WITH_STATISTICS
116 /*
117 * Error code stats.
118 */
119 if (uErr & X86_TRAP_PF_US)
120 {
121 if (!(uErr & X86_TRAP_PF_P))
122 {
123 if (uErr & X86_TRAP_PF_RW)
124 STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eUSNotPresentWrite);
125 else
126 STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eUSNotPresentRead);
127 }
128 else if (uErr & X86_TRAP_PF_RW)
129 STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eUSWrite);
130 else if (uErr & X86_TRAP_PF_RSVD)
131 STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eUSReserved);
132 else if (uErr & X86_TRAP_PF_ID)
133 STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eUSNXE);
134 else
135 STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eUSRead);
136 }
137 else
138 { /* Supervisor */
139 if (!(uErr & X86_TRAP_PF_P))
140 {
141 if (uErr & X86_TRAP_PF_RW)
142 STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eSVNotPresentWrite);
143 else
144 STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eSVNotPresentRead);
145 }
146 else if (uErr & X86_TRAP_PF_RW)
147 STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eSVWrite);
148 else if (uErr & X86_TRAP_PF_ID)
149 STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eSNXE);
150 else if (uErr & X86_TRAP_PF_RSVD)
151 STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eSVReserved);
152 }
153#endif
154
155 /*
156 * Call the worker.
157 *
158 * We pretend the guest is in protected mode without paging, so we can use existing code to build the
159 * nested page tables.
160 */
161 switch(enmShwPagingMode)
162 {
163 case PGMMODE_32_BIT:
164 rc = PGM_BTH_NAME_32BIT_PROT(Trap0eHandler)(pVM, uErr, pRegFrame, pvFault);
165 break;
166 case PGMMODE_PAE:
167 case PGMMODE_PAE_NX:
168 rc = PGM_BTH_NAME_PAE_PROT(Trap0eHandler)(pVM, uErr, pRegFrame, pvFault);
169 break;
170 case PGMMODE_AMD64:
171 case PGMMODE_AMD64_NX:
172 rc = PGM_BTH_NAME_AMD64_PROT(Trap0eHandler)(pVM, uErr, pRegFrame, pvFault);
173 break;
174 case PGMMODE_EPT:
175 rc = PGM_BTH_NAME_EPT_PROT(Trap0eHandler)(pVM, uErr, pRegFrame, pvFault);
176 break;
177 default:
178 AssertFailed();
179 rc = VERR_INVALID_PARAMETER;
180 break;
181 }
182 if (rc == VINF_PGM_SYNCPAGE_MODIFIED_PDE)
183 rc = VINF_SUCCESS;
184 STAM_STATS({ if (!pVM->pgm.s.CTX_SUFF(pStatTrap0eAttribution))
185 pVM->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVM->pgm.s.StatRZTrap0eTime2Misc; });
186 STAM_PROFILE_STOP_EX(&pVM->pgm.s.StatRZTrap0e, pVM->pgm.s.CTX_SUFF(pStatTrap0eAttribution), a);
187 return rc;
188}
189
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette