Added methods {Allocate,Free}32BitPage(), which allocate+map/unmap+free a

page with a 32 bit physical address (needed for the PDPTs). A small set of
free pages is cached, so the rather expensive vm_page_allocate_page_run() can
be avoided most of the time.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37088 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2010-06-10 17:38:47 +00:00
parent f498c07968
commit 5d89694992
2 changed files with 96 additions and 1 deletions
@@ -13,7 +13,9 @@
#include <stdlib.h>
#include <string.h>
#include <util/AutoLock.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <vm/VMAddressSpace.h>
#include "paging/32bit/paging.h"
@@ -38,6 +40,10 @@
using X86LargePhysicalPageMapper::PhysicalPageSlot;
// number of 32 bit pages that will be cached
static const page_num_t kMaxFree32BitPagesCount = 32;
// #pragma mark - ToPAESwitcher
@@ -472,8 +478,11 @@ X86PagingMethodPAE::PhysicalPageSlotPool::AllocatePool(
X86PagingMethodPAE::X86PagingMethodPAE()
:
fPhysicalPageMapper(NULL),
fKernelPhysicalPageMapper(NULL)
fKernelPhysicalPageMapper(NULL),
fFreePages(NULL),
fFreePagesCount(0)
{
mutex_init(&fFreePagesLock, "x86 PAE free pages");
}
@@ -528,6 +537,14 @@ X86PagingMethodPAE::InitPostArea(kernel_args* args)
if (error != B_OK)
return error;
// The early physical page mapping mechanism is no longer needed. Unmap the
// slot.
*fFreeVirtualSlotPTE = 0;
invalidate_TLB(fFreeVirtualSlot);
fFreeVirtualSlotPTE = NULL;
fFreeVirtualSlot = 0;
return B_OK;
}
@@ -645,6 +662,71 @@ X86PagingMethodPAE::PutPageTableEntryInTable(pae_page_table_entry* entry,
}
void*
X86PagingMethodPAE::Allocate32BitPage(phys_addr_t& _physicalAddress,
void*& _handle)
{
// get a free page
MutexLocker locker(fFreePagesLock);
vm_page* page;
if (fFreePages != NULL) {
page = fFreePages;
fFreePages = page->cache_next;
fFreePagesCount--;
locker.Unlock();
} else {
// no pages -- allocate one
locker.Unlock();
page = vm_page_allocate_page_run(PAGE_STATE_UNUSED, 0, 0x100000000LL, 1,
VM_PRIORITY_SYSTEM);
DEBUG_PAGE_ACCESS_END(page);
if (page == NULL)
return NULL;
}
// map the page
phys_addr_t physicalAddress
= (phys_addr_t)page->physical_page_number * B_PAGE_SIZE;
addr_t virtualAddress;
if (fPhysicalPageMapper->GetPage(physicalAddress, &virtualAddress, &_handle)
!= B_OK) {
// mapping failed -- free page
locker.Lock();
page->cache_next = fFreePages;
fFreePages = page;
fFreePagesCount++;
return NULL;
}
_physicalAddress = physicalAddress;
return (void*)virtualAddress;
}
void
X86PagingMethodPAE::Free32BitPage(void* address, phys_addr_t physicalAddress,
void* handle)
{
// unmap the page
fPhysicalPageMapper->PutPage((addr_t)address, handle);
// free it
vm_page* page = vm_lookup_page(physicalAddress / B_PAGE_SIZE);
MutexLocker locker(fFreePagesLock);
if (fFreePagesCount < kMaxFree32BitPagesCount) {
// cache not full yet -- cache it
page->cache_next = fFreePages;
fFreePages = page;
fFreePagesCount++;
} else {
// cache full -- free it
locker.Unlock();
DEBUG_PAGE_ACCESS_START(page);
vm_page_free(NULL, page);
}
}
bool
X86PagingMethodPAE::_EarlyQuery(addr_t virtualAddress,
phys_addr_t* _physicalAddress)
@@ -8,6 +8,9 @@
#include <KernelExport.h>
#include <lock.h>
#include <vm/vm_types.h>
#include "paging/pae/paging.h"
#include "paging/X86PagingMethod.h"
#include "paging/X86PagingStructures.h"
@@ -41,6 +44,12 @@ public:
virtual bool IsKernelPageAccessible(addr_t virtualAddress,
uint32 protection);
void* Allocate32BitPage(
phys_addr_t& _physicalAddress,
void*& _handle);
void Free32BitPage(void* address,
phys_addr_t physicalAddress, void* handle);
inline X86PhysicalPageMapper* PhysicalPageMapper() const
{ return fPhysicalPageMapper; }
inline TranslationMapPhysicalPageMapper* KernelPhysicalPageMapper() const
@@ -108,6 +117,10 @@ private:
phys_addr_t fKernelPhysicalPageDirs[4];
addr_t fFreeVirtualSlot;
pae_page_table_entry* fFreeVirtualSlotPTE;
mutex fFreePagesLock;
vm_page* fFreePages;
page_num_t fFreePagesCount;
};