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:
@@ -13,7 +13,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <util/AutoLock.h>
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
|
#include <vm/vm_page.h>
|
||||||
#include <vm/VMAddressSpace.h>
|
#include <vm/VMAddressSpace.h>
|
||||||
|
|
||||||
#include "paging/32bit/paging.h"
|
#include "paging/32bit/paging.h"
|
||||||
@@ -38,6 +40,10 @@
|
|||||||
using X86LargePhysicalPageMapper::PhysicalPageSlot;
|
using X86LargePhysicalPageMapper::PhysicalPageSlot;
|
||||||
|
|
||||||
|
|
||||||
|
// number of 32 bit pages that will be cached
|
||||||
|
static const page_num_t kMaxFree32BitPagesCount = 32;
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - ToPAESwitcher
|
// #pragma mark - ToPAESwitcher
|
||||||
|
|
||||||
|
|
||||||
@@ -472,8 +478,11 @@ X86PagingMethodPAE::PhysicalPageSlotPool::AllocatePool(
|
|||||||
X86PagingMethodPAE::X86PagingMethodPAE()
|
X86PagingMethodPAE::X86PagingMethodPAE()
|
||||||
:
|
:
|
||||||
fPhysicalPageMapper(NULL),
|
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)
|
if (error != B_OK)
|
||||||
return error;
|
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;
|
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
|
bool
|
||||||
X86PagingMethodPAE::_EarlyQuery(addr_t virtualAddress,
|
X86PagingMethodPAE::_EarlyQuery(addr_t virtualAddress,
|
||||||
phys_addr_t* _physicalAddress)
|
phys_addr_t* _physicalAddress)
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
#include <lock.h>
|
||||||
|
#include <vm/vm_types.h>
|
||||||
|
|
||||||
#include "paging/pae/paging.h"
|
#include "paging/pae/paging.h"
|
||||||
#include "paging/X86PagingMethod.h"
|
#include "paging/X86PagingMethod.h"
|
||||||
#include "paging/X86PagingStructures.h"
|
#include "paging/X86PagingStructures.h"
|
||||||
@@ -41,6 +44,12 @@ public:
|
|||||||
virtual bool IsKernelPageAccessible(addr_t virtualAddress,
|
virtual bool IsKernelPageAccessible(addr_t virtualAddress,
|
||||||
uint32 protection);
|
uint32 protection);
|
||||||
|
|
||||||
|
void* Allocate32BitPage(
|
||||||
|
phys_addr_t& _physicalAddress,
|
||||||
|
void*& _handle);
|
||||||
|
void Free32BitPage(void* address,
|
||||||
|
phys_addr_t physicalAddress, void* handle);
|
||||||
|
|
||||||
inline X86PhysicalPageMapper* PhysicalPageMapper() const
|
inline X86PhysicalPageMapper* PhysicalPageMapper() const
|
||||||
{ return fPhysicalPageMapper; }
|
{ return fPhysicalPageMapper; }
|
||||||
inline TranslationMapPhysicalPageMapper* KernelPhysicalPageMapper() const
|
inline TranslationMapPhysicalPageMapper* KernelPhysicalPageMapper() const
|
||||||
@@ -108,6 +117,10 @@ private:
|
|||||||
phys_addr_t fKernelPhysicalPageDirs[4];
|
phys_addr_t fKernelPhysicalPageDirs[4];
|
||||||
addr_t fFreeVirtualSlot;
|
addr_t fFreeVirtualSlot;
|
||||||
pae_page_table_entry* fFreeVirtualSlotPTE;
|
pae_page_table_entry* fFreeVirtualSlotPTE;
|
||||||
|
|
||||||
|
mutex fFreePagesLock;
|
||||||
|
vm_page* fFreePages;
|
||||||
|
page_num_t fFreePagesCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user