VirtualBox

source: vbox/trunk/src/VBox/VMM/PGMBth.h@ 30037

Last change on this file since 30037 was 28800, checked in by vboxsync, 14 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.6 KB
Line 
1/* $Id: PGMBth.h 28800 2010-04-27 08:22:32Z vboxsync $ */
2/** @file
3 * VBox - Page Manager / Monitor, Shadow+Guest Paging Template.
4 */
5
6/*
7 * Copyright (C) 2006-2007 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
18
19/*******************************************************************************
20* Internal Functions *
21*******************************************************************************/
22RT_C_DECLS_BEGIN
23PGM_BTH_DECL(int, InitData)(PVM pVM, PPGMMODEDATA pModeData, bool fResolveGCAndR0);
24PGM_BTH_DECL(int, Enter)(PVMCPU pVCpu, RTGCPHYS GCPhysCR3);
25PGM_BTH_DECL(int, Relocate)(PVMCPU pVCpu, RTGCPTR offDelta);
26
27PGM_BTH_DECL(int, Trap0eHandler)(PVMCPU pVCpu, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, bool *pfLockTaken);
28PGM_BTH_DECL(int, SyncCR3)(PVMCPU pVCpu, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal);
29PGM_BTH_DECL(int, SyncPage)(PVMCPU pVCpu, X86PDE PdeSrc, RTGCPTR GCPtrPage, unsigned cPages, unsigned uError);
30PGM_BTH_DECL(int, VerifyAccessSyncPage)(PVMCPU pVCpu, RTGCPTR Addr, unsigned fPage, unsigned uError);
31PGM_BTH_DECL(int, InvalidatePage)(PVMCPU pVCpu, RTGCPTR GCPtrPage);
32PGM_BTH_DECL(int, PrefetchPage)(PVMCPU pVCpu, RTGCPTR GCPtrPage);
33PGM_BTH_DECL(unsigned, AssertCR3)(PVMCPU pVCpu, uint64_t cr3, uint64_t cr4, RTGCPTR GCPtr = 0, RTGCPTR cb = ~(RTGCPTR)0);
34PGM_BTH_DECL(int, MapCR3)(PVMCPU pVCpu, RTGCPHYS GCPhysCR3);
35PGM_BTH_DECL(int, UnmapCR3)(PVMCPU pVCpu);
36RT_C_DECLS_END
37
38
39/**
40 * Initializes the both bit of the paging mode data.
41 *
42 * @returns VBox status code.
43 * @param pVM The VM handle.
44 * @param fResolveGCAndR0 Indicate whether or not GC and Ring-0 symbols can be resolved now.
45 * This is used early in the init process to avoid trouble with PDM
46 * not being initialized yet.
47 */
48PGM_BTH_DECL(int, InitData)(PVM pVM, PPGMMODEDATA pModeData, bool fResolveGCAndR0)
49{
50 Assert(pModeData->uShwType == PGM_SHW_TYPE); Assert(pModeData->uGstType == PGM_GST_TYPE);
51
52 /* Ring 3 */
53 pModeData->pfnR3BthRelocate = PGM_BTH_NAME(Relocate);
54 pModeData->pfnR3BthSyncCR3 = PGM_BTH_NAME(SyncCR3);
55 pModeData->pfnR3BthInvalidatePage = PGM_BTH_NAME(InvalidatePage);
56 pModeData->pfnR3BthSyncPage = PGM_BTH_NAME(SyncPage);
57 pModeData->pfnR3BthPrefetchPage = PGM_BTH_NAME(PrefetchPage);
58 pModeData->pfnR3BthVerifyAccessSyncPage = PGM_BTH_NAME(VerifyAccessSyncPage);
59#ifdef VBOX_STRICT
60 pModeData->pfnR3BthAssertCR3 = PGM_BTH_NAME(AssertCR3);
61#endif
62 pModeData->pfnR3BthMapCR3 = PGM_BTH_NAME(MapCR3);
63 pModeData->pfnR3BthUnmapCR3 = PGM_BTH_NAME(UnmapCR3);
64
65 if (fResolveGCAndR0)
66 {
67 int rc;
68
69#if PGM_SHW_TYPE != PGM_TYPE_AMD64 && PGM_SHW_TYPE != PGM_TYPE_NESTED && PGM_SHW_TYPE != PGM_TYPE_EPT /* No AMD64 for traditional virtualization, only VT-x and AMD-V. */
70 /* GC */
71 rc = PDMR3LdrGetSymbolRC(pVM, NULL, PGM_BTH_NAME_RC_STR(Trap0eHandler), &pModeData->pfnRCBthTrap0eHandler);
72 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_RC_STR(Trap0eHandler), rc), rc);
73 rc = PDMR3LdrGetSymbolRC(pVM, NULL, PGM_BTH_NAME_RC_STR(InvalidatePage), &pModeData->pfnRCBthInvalidatePage);
74 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_RC_STR(InvalidatePage), rc), rc);
75 rc = PDMR3LdrGetSymbolRC(pVM, NULL, PGM_BTH_NAME_RC_STR(SyncCR3), &pModeData->pfnRCBthSyncCR3);
76 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_RC_STR(SyncPage), rc), rc);
77 rc = PDMR3LdrGetSymbolRC(pVM, NULL, PGM_BTH_NAME_RC_STR(SyncPage), &pModeData->pfnRCBthSyncPage);
78 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_RC_STR(SyncPage), rc), rc);
79 rc = PDMR3LdrGetSymbolRC(pVM, NULL, PGM_BTH_NAME_RC_STR(PrefetchPage), &pModeData->pfnRCBthPrefetchPage);
80 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_RC_STR(PrefetchPage), rc), rc);
81 rc = PDMR3LdrGetSymbolRC(pVM, NULL, PGM_BTH_NAME_RC_STR(VerifyAccessSyncPage),&pModeData->pfnRCBthVerifyAccessSyncPage);
82 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_RC_STR(VerifyAccessSyncPage), rc), rc);
83# ifdef VBOX_STRICT
84 rc = PDMR3LdrGetSymbolRC(pVM, NULL, PGM_BTH_NAME_RC_STR(AssertCR3), &pModeData->pfnRCBthAssertCR3);
85 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_RC_STR(AssertCR3), rc), rc);
86# endif
87 rc = PDMR3LdrGetSymbolRC(pVM, NULL, PGM_BTH_NAME_RC_STR(MapCR3), &pModeData->pfnRCBthMapCR3);
88 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_RC_STR(MapCR3), rc), rc);
89 rc = PDMR3LdrGetSymbolRC(pVM, NULL, PGM_BTH_NAME_RC_STR(UnmapCR3), &pModeData->pfnRCBthUnmapCR3);
90 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_RC_STR(UnmapCR3), rc), rc);
91#endif /* Not AMD64 shadow paging. */
92
93 /* Ring 0 */
94 rc = PDMR3LdrGetSymbolR0(pVM, NULL, PGM_BTH_NAME_R0_STR(Trap0eHandler), &pModeData->pfnR0BthTrap0eHandler);
95 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_R0_STR(Trap0eHandler), rc), rc);
96 rc = PDMR3LdrGetSymbolR0(pVM, NULL, PGM_BTH_NAME_R0_STR(InvalidatePage), &pModeData->pfnR0BthInvalidatePage);
97 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_R0_STR(InvalidatePage), rc), rc);
98 rc = PDMR3LdrGetSymbolR0(pVM, NULL, PGM_BTH_NAME_R0_STR(SyncCR3), &pModeData->pfnR0BthSyncCR3);
99 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_R0_STR(SyncCR3), rc), rc);
100 rc = PDMR3LdrGetSymbolR0(pVM, NULL, PGM_BTH_NAME_R0_STR(SyncPage), &pModeData->pfnR0BthSyncPage);
101 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_R0_STR(SyncPage), rc), rc);
102 rc = PDMR3LdrGetSymbolR0(pVM, NULL, PGM_BTH_NAME_R0_STR(PrefetchPage), &pModeData->pfnR0BthPrefetchPage);
103 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_R0_STR(PrefetchPage), rc), rc);
104 rc = PDMR3LdrGetSymbolR0(pVM, NULL, PGM_BTH_NAME_R0_STR(VerifyAccessSyncPage),&pModeData->pfnR0BthVerifyAccessSyncPage);
105 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_R0_STR(VerifyAccessSyncPage), rc), rc);
106#ifdef VBOX_STRICT
107 rc = PDMR3LdrGetSymbolR0(pVM, NULL, PGM_BTH_NAME_R0_STR(AssertCR3), &pModeData->pfnR0BthAssertCR3);
108 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_R0_STR(AssertCR3), rc), rc);
109#endif
110 rc = PDMR3LdrGetSymbolR0(pVM, NULL, PGM_BTH_NAME_R0_STR(MapCR3), &pModeData->pfnR0BthMapCR3);
111 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_R0_STR(MapCR3), rc), rc);
112 rc = PDMR3LdrGetSymbolR0(pVM, NULL, PGM_BTH_NAME_R0_STR(UnmapCR3), &pModeData->pfnR0BthUnmapCR3);
113 AssertMsgRCReturn(rc, ("%s -> rc=%Rrc\n", PGM_BTH_NAME_R0_STR(UnmapCR3), rc), rc);
114 }
115 return VINF_SUCCESS;
116}
117
118
119/**
120 * Enters the shadow+guest mode.
121 *
122 * @returns VBox status code.
123 * @param pVM VM handle.
124 * @param pVCpu The VMCPU to operate on.
125 * @param GCPhysCR3 The physical address from the CR3 register.
126 */
127PGM_BTH_DECL(int, Enter)(PVMCPU pVCpu, RTGCPHYS GCPhysCR3)
128{
129 /* Here we deal with allocation of the root shadow page table for real and protected mode during mode switches;
130 * Other modes rely on MapCR3/UnmapCR3 to setup the shadow root page tables.
131 */
132#if ( ( PGM_SHW_TYPE == PGM_TYPE_32BIT \
133 || PGM_SHW_TYPE == PGM_TYPE_PAE \
134 || PGM_SHW_TYPE == PGM_TYPE_AMD64) \
135 && ( PGM_GST_TYPE == PGM_TYPE_REAL \
136 || PGM_GST_TYPE == PGM_TYPE_PROT))
137
138 PVM pVM = pVCpu->pVMR3;
139
140 Assert(!HWACCMIsNestedPagingActive(pVM));
141
142 pgmLock(pVM);
143 /* Note: we only really need shadow paging in real and protected mode for VT-x and AMD-V (excluding nested paging/EPT modes),
144 * but any calls to GC need a proper shadow page setup as well.
145 */
146 /* Free the previous root mapping if still active. */
147 PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool);
148 if (pVCpu->pgm.s.CTX_SUFF(pShwPageCR3))
149 {
150 Assert(pVCpu->pgm.s.pShwPageCR3R3->enmKind != PGMPOOLKIND_FREE);
151
152 /* Mark the page as unlocked; allow flushing again. */
153 pgmPoolUnlockPage(pPool, pVCpu->pgm.s.CTX_SUFF(pShwPageCR3));
154
155 /* Remove the hypervisor mappings from the shadow page table. */
156 pgmMapDeactivateCR3(pVM, pVCpu->pgm.s.CTX_SUFF(pShwPageCR3));
157
158 pgmPoolFreeByPage(pPool, pVCpu->pgm.s.pShwPageCR3R3, pVCpu->pgm.s.iShwUser, pVCpu->pgm.s.iShwUserTable);
159 pVCpu->pgm.s.pShwPageCR3R3 = 0;
160 pVCpu->pgm.s.pShwPageCR3RC = 0;
161 pVCpu->pgm.s.pShwPageCR3R0 = 0;
162 pVCpu->pgm.s.iShwUser = 0;
163 pVCpu->pgm.s.iShwUserTable = 0;
164 }
165
166 /* contruct a fake address. */
167 GCPhysCR3 = RT_BIT_64(63);
168 pVCpu->pgm.s.iShwUser = SHW_POOL_ROOT_IDX;
169 pVCpu->pgm.s.iShwUserTable = GCPhysCR3 >> PAGE_SHIFT;
170 int rc = pgmPoolAlloc(pVM, GCPhysCR3, BTH_PGMPOOLKIND_ROOT, pVCpu->pgm.s.iShwUser, pVCpu->pgm.s.iShwUserTable, &pVCpu->pgm.s.pShwPageCR3R3);
171 if (rc == VERR_PGM_POOL_FLUSHED)
172 {
173 Log(("Bth-Enter: PGM pool flushed -> signal sync cr3\n"));
174 Assert(VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
175 pgmUnlock(pVM);
176 return VINF_PGM_SYNC_CR3;
177 }
178 AssertRCReturn(rc, rc);
179
180 /* Mark the page as locked; disallow flushing. */
181 pgmPoolLockPage(pPool, pVCpu->pgm.s.pShwPageCR3R3);
182
183 pVCpu->pgm.s.pShwPageCR3R0 = MMHyperCCToR0(pVM, pVCpu->pgm.s.pShwPageCR3R3);
184 pVCpu->pgm.s.pShwPageCR3RC = MMHyperCCToRC(pVM, pVCpu->pgm.s.pShwPageCR3R3);
185
186 /* Set the current hypervisor CR3. */
187 CPUMSetHyperCR3(pVCpu, PGMGetHyperCR3(pVCpu));
188
189 /* Apply all hypervisor mappings to the new CR3. */
190 rc = pgmMapActivateCR3(pVM, pVCpu->pgm.s.CTX_SUFF(pShwPageCR3));
191 pgmUnlock(pVM);
192 return rc;
193#else
194 return VINF_SUCCESS;
195#endif
196}
197
198
199/**
200 * Relocate any GC pointers related to shadow mode paging.
201 *
202 * @returns VBox status code.
203 * @param pVM The VM handle.
204 * @param pVCpu The VMCPU to operate on.
205 * @param offDelta The reloation offset.
206 */
207PGM_BTH_DECL(int, Relocate)(PVMCPU pVCpu, RTGCPTR offDelta)
208{
209 /* nothing special to do here - InitData does the job. */
210 return VINF_SUCCESS;
211}
212
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use