1
/* $Id: MMAllPagePool.cpp 4071 2007-08-07 17:07:59Z vboxsync $ */
3
* MM - Memory Monitor(/Manager) - Page Pool.
7
* Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13
* in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14
* distribution. VirtualBox OSE is distributed in the hope that it will
15
* be useful, but WITHOUT ANY WARRANTY of any kind.
18
/*******************************************************************************
20
*******************************************************************************/
21
#define LOG_GROUP LOG_GROUP_MM_POOL
24
#include <VBox/stam.h>
25
#include "MMInternal.h"
27
#include <VBox/param.h>
30
#include <iprt/alloc.h>
31
#include <iprt/assert.h>
32
#include <iprt/string.h>
33
#define USE_INLINE_ASM_BIT_OPS
34
#ifdef USE_INLINE_ASM_BIT_OPS
35
# include <iprt/asm.h>
41
* Converts a pool address to a physical address.
42
* The specified allocation type must match with the address.
44
* @returns Physical address.
45
* @returns NIL_RTHCPHYS if not found or eType is not matching.
46
* @param pPool Pointer to the page pool.
47
* @param pv The address to convert.
48
* @thread The Emulation Thread.
50
MMDECL(RTHCPHYS) mmPagePoolPtr2Phys(PMMPAGEPOOL pPool, void *pv)
53
VM_ASSERT_EMT(pPool->pVM);
56
* Lookup the virtual address.
58
PMMPPLOOKUPHCPTR pLookup = (PMMPPLOOKUPHCPTR)RTAvlPVGetBestFit(&pPool->pLookupVirt, pv, false);
61
unsigned iPage = ((char *)pv - (char *)pLookup->pSubPool->pvPages) >> PAGE_SHIFT;
62
if (iPage < pLookup->pSubPool->cPages)
65
* Convert the virtual address to a physical address.
67
STAM_COUNTER_INC(&pPool->cToPhysCalls);
68
AssertMsg( pLookup->pSubPool->paPhysPages[iPage].Phys
69
&& !(pLookup->pSubPool->paPhysPages[iPage].Phys & PAGE_OFFSET_MASK),
70
("Phys=%#x\n", pLookup->pSubPool->paPhysPages[iPage].Phys));
71
AssertMsg((uintptr_t)pLookup->pSubPool == pLookup->pSubPool->paPhysPages[iPage].uReserved,
72
("pSubPool=%p uReserved=%p\n", pLookup->pSubPool, pLookup->pSubPool->paPhysPages[iPage].uReserved));
73
return pLookup->pSubPool->paPhysPages[iPage].Phys + ((uintptr_t)pv & PAGE_OFFSET_MASK);
80
* Converts a pool physical address to a linear address.
81
* The specified allocation type must match with the address.
83
* @returns Physical address.
84
* @returns NULL if not found or eType is not matching.
85
* @param pPool Pointer to the page pool.
86
* @param HCPhys The address to convert.
87
* @thread The Emulation Thread.
89
MMDECL(void *) mmPagePoolPhys2Ptr(PMMPAGEPOOL pPool, RTHCPHYS HCPhys)
91
#if 0 /** @todo have to fix the debugger, but until then this is going on my nevers. */
93
VM_ASSERT_EMT(pPool->pVM);
98
* Lookup the virtual address.
100
PMMPPLOOKUPHCPHYS pLookup = (PMMPPLOOKUPHCPHYS)RTAvlHCPhysGet(&pPool->pLookupPhys, HCPhys & X86_PTE_PAE_PG_MASK);
103
STAM_COUNTER_INC(&pPool->cToVirtCalls);
104
PSUPPAGE pPhysPage = pLookup->pPhysPage;
105
PMMPAGESUBPOOL pSubPool = (PMMPAGESUBPOOL)pPhysPage->uReserved;
106
unsigned iPage = pPhysPage - pSubPool->paPhysPages;
107
return (char *)pSubPool->pvPages + (HCPhys & PAGE_OFFSET_MASK) + (iPage << PAGE_SHIFT);
114
* Convert a page in the page pool to a HC physical address.
115
* This works for pages allocated by MMR3PageAlloc(), MMR3PageAllocPhys()
116
* and MMR3PageAllocLow().
118
* @returns Physical address for the specified page table.
119
* @param pVM VM handle.
120
* @param pvPage Page which physical address we query.
121
* @thread The Emulation Thread.
123
MMDECL(RTHCPHYS) MMPage2Phys(PVM pVM, void *pvPage)
125
RTHCPHYS HCPhys = mmPagePoolPtr2Phys(pVM->mm.s.pPagePool, pvPage);
126
if (HCPhys == NIL_RTHCPHYS)
128
HCPhys = mmPagePoolPtr2Phys(pVM->mm.s.pPagePoolLow, pvPage);
129
if (HCPhys == NIL_RTHCPHYS)
131
STAM_COUNTER_INC(&pVM->mm.s.pPagePool->cErrors);
132
AssertMsgFailed(("Invalid pvPage=%p specified\n", pvPage));
140
* Convert physical address of a page to a HC virtual address.
141
* This works for pages allocated by MMR3PageAlloc(), MMR3PageAllocPhys()
142
* and MMR3PageAllocLow().
144
* @returns Pointer to the page at that physical address.
145
* @param pVM VM handle.
146
* @param HCPhysPage The physical address of a page.
147
* @thread The Emulation Thread.
149
MMDECL(void *) MMPagePhys2Page(PVM pVM, RTHCPHYS HCPhysPage)
151
void *pvPage = mmPagePoolPhys2Ptr(pVM->mm.s.pPagePool, HCPhysPage);
154
pvPage = mmPagePoolPhys2Ptr(pVM->mm.s.pPagePoolLow, HCPhysPage);
157
STAM_COUNTER_INC(&pVM->mm.s.pPagePool->cErrors);
158
AssertMsg(pvPage, ("Invalid HCPhysPage=%VHp specified\n", HCPhysPage));
166
* Convert physical address of a page to a HC virtual address.
167
* This works for pages allocated by MMR3PageAlloc(), MMR3PageAllocPhys()
168
* and MMR3PageAllocLow().
170
* @returns VBox status code.
171
* @param pVM VM handle.
172
* @param HCPhysPage The physical address of a page.
173
* @param ppvPage Where to store the address corresponding to HCPhysPage.
174
* @thread The Emulation Thread.
176
MMDECL(int) MMPagePhys2PageEx(PVM pVM, RTHCPHYS HCPhysPage, void **ppvPage)
178
void *pvPage = mmPagePoolPhys2Ptr(pVM->mm.s.pPagePool, HCPhysPage);
181
pvPage = mmPagePoolPhys2Ptr(pVM->mm.s.pPagePoolLow, HCPhysPage);
184
STAM_COUNTER_INC(&pVM->mm.s.pPagePool->cErrors);
185
AssertMsg(pvPage, ("Invalid HCPhysPage=%VHp specified\n", HCPhysPage));
186
return VERR_INVALID_POINTER;
195
* Try convert physical address of a page to a HC virtual address.
196
* This works for pages allocated by MMR3PageAlloc(), MMR3PageAllocPhys()
197
* and MMR3PageAllocLow().
199
* @returns VBox status code.
200
* @param pVM VM handle.
201
* @param HCPhysPage The physical address of a page.
202
* @param ppvPage Where to store the address corresponding to HCPhysPage.
203
* @thread The Emulation Thread.
205
MMDECL(int) MMPagePhys2PageTry(PVM pVM, RTHCPHYS HCPhysPage, void **ppvPage)
207
void *pvPage = mmPagePoolPhys2Ptr(pVM->mm.s.pPagePool, HCPhysPage);
210
pvPage = mmPagePoolPhys2Ptr(pVM->mm.s.pPagePoolLow, HCPhysPage);
212
return VERR_INVALID_POINTER;