Made X86PhysicalPageMapper and the large memory implementation paging method
agnostic: * Changed return value of X86PhysicalPageMapper::[Interrupt]GetPageTableAt() from page_table_entry* to void*. * Made PhysicalPageSlotPool an abstract base class. The paging method provides an implementation and creates the pools now. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37054 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
#include <vm/VMCache.h>
|
#include <vm/VMCache.h>
|
||||||
|
|
||||||
#include "x86_physical_page_mapper.h"
|
#include "x86_physical_page_mapper.h"
|
||||||
|
#include "x86_physical_page_mapper_large_memory.h"
|
||||||
#include "X86VMTranslationMap.h"
|
#include "X86VMTranslationMap.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -40,6 +41,12 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
using X86LargePhysicalPageMapper::PhysicalPageSlot;
|
||||||
|
|
||||||
|
|
||||||
|
static const size_t kPageTableAlignment = 1024 * B_PAGE_SIZE;
|
||||||
|
|
||||||
|
|
||||||
static X86PagingMethod32Bit sMethod;
|
static X86PagingMethod32Bit sMethod;
|
||||||
|
|
||||||
static page_table_entry *sPageHole = NULL;
|
static page_table_entry *sPageHole = NULL;
|
||||||
@@ -474,7 +481,7 @@ X86VMTranslationMap::Map(addr_t va, phys_addr_t pa, uint32 attributes,
|
|||||||
struct thread* thread = thread_get_current_thread();
|
struct thread* thread = thread_get_current_thread();
|
||||||
ThreadCPUPinner pinner(thread);
|
ThreadCPUPinner pinner(thread);
|
||||||
|
|
||||||
page_table_entry* pt = fPageMapper->GetPageTableAt(
|
page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt(
|
||||||
pd[index] & X86_PDE_ADDRESS_MASK);
|
pd[index] & X86_PDE_ADDRESS_MASK);
|
||||||
index = VADDR_TO_PTENT(va);
|
index = VADDR_TO_PTENT(va);
|
||||||
|
|
||||||
@@ -522,7 +529,7 @@ restart:
|
|||||||
struct thread* thread = thread_get_current_thread();
|
struct thread* thread = thread_get_current_thread();
|
||||||
ThreadCPUPinner pinner(thread);
|
ThreadCPUPinner pinner(thread);
|
||||||
|
|
||||||
page_table_entry* pt = fPageMapper->GetPageTableAt(
|
page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt(
|
||||||
pd[index] & X86_PDE_ADDRESS_MASK);
|
pd[index] & X86_PDE_ADDRESS_MASK);
|
||||||
|
|
||||||
for (index = VADDR_TO_PTENT(start); (index < 1024) && (start < end);
|
for (index = VADDR_TO_PTENT(start); (index < 1024) && (start < end);
|
||||||
@@ -576,7 +583,7 @@ X86VMTranslationMap::UnmapPage(VMArea* area, addr_t address,
|
|||||||
|
|
||||||
ThreadCPUPinner pinner(thread_get_current_thread());
|
ThreadCPUPinner pinner(thread_get_current_thread());
|
||||||
|
|
||||||
page_table_entry* pt = fPageMapper->GetPageTableAt(
|
page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt(
|
||||||
pd[index] & X86_PDE_ADDRESS_MASK);
|
pd[index] & X86_PDE_ADDRESS_MASK);
|
||||||
|
|
||||||
index = VADDR_TO_PTENT(address);
|
index = VADDR_TO_PTENT(address);
|
||||||
@@ -700,7 +707,7 @@ X86VMTranslationMap::UnmapPages(VMArea* area, addr_t base, size_t size,
|
|||||||
struct thread* thread = thread_get_current_thread();
|
struct thread* thread = thread_get_current_thread();
|
||||||
ThreadCPUPinner pinner(thread);
|
ThreadCPUPinner pinner(thread);
|
||||||
|
|
||||||
page_table_entry* pt = fPageMapper->GetPageTableAt(
|
page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt(
|
||||||
pd[index] & X86_PDE_ADDRESS_MASK);
|
pd[index] & X86_PDE_ADDRESS_MASK);
|
||||||
|
|
||||||
for (index = VADDR_TO_PTENT(start); (index < 1024) && (start < end);
|
for (index = VADDR_TO_PTENT(start); (index < 1024) && (start < end);
|
||||||
@@ -837,8 +844,9 @@ X86VMTranslationMap::UnmapArea(VMArea* area, bool deletingAddressSpace,
|
|||||||
|
|
||||||
ThreadCPUPinner pinner(thread_get_current_thread());
|
ThreadCPUPinner pinner(thread_get_current_thread());
|
||||||
|
|
||||||
page_table_entry* pt = fPageMapper->GetPageTableAt(
|
page_table_entry* pt
|
||||||
pd[index] & X86_PDE_ADDRESS_MASK);
|
= (page_table_entry*)fPageMapper->GetPageTableAt(
|
||||||
|
pd[index] & X86_PDE_ADDRESS_MASK);
|
||||||
page_table_entry oldEntry = clear_page_table_entry(
|
page_table_entry oldEntry = clear_page_table_entry(
|
||||||
&pt[VADDR_TO_PTENT(address)]);
|
&pt[VADDR_TO_PTENT(address)]);
|
||||||
|
|
||||||
@@ -913,7 +921,7 @@ X86VMTranslationMap::Query(addr_t va, phys_addr_t *_physical, uint32 *_flags)
|
|||||||
struct thread* thread = thread_get_current_thread();
|
struct thread* thread = thread_get_current_thread();
|
||||||
ThreadCPUPinner pinner(thread);
|
ThreadCPUPinner pinner(thread);
|
||||||
|
|
||||||
page_table_entry* pt = fPageMapper->GetPageTableAt(
|
page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt(
|
||||||
pd[index] & X86_PDE_ADDRESS_MASK);
|
pd[index] & X86_PDE_ADDRESS_MASK);
|
||||||
page_table_entry entry = pt[VADDR_TO_PTENT(va)];
|
page_table_entry entry = pt[VADDR_TO_PTENT(va)];
|
||||||
|
|
||||||
@@ -954,8 +962,9 @@ X86VMTranslationMap::QueryInterrupt(addr_t va, phys_addr_t *_physical,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// map page table entry
|
// map page table entry
|
||||||
page_table_entry* pt = sPhysicalPageMapper->InterruptGetPageTableAt(
|
page_table_entry* pt
|
||||||
pd[index] & X86_PDE_ADDRESS_MASK);
|
= (page_table_entry*)sPhysicalPageMapper->InterruptGetPageTableAt(
|
||||||
|
pd[index] & X86_PDE_ADDRESS_MASK);
|
||||||
page_table_entry entry = pt[VADDR_TO_PTENT(va)];
|
page_table_entry entry = pt[VADDR_TO_PTENT(va)];
|
||||||
|
|
||||||
*_physical = entry & X86_PDE_ADDRESS_MASK;
|
*_physical = entry & X86_PDE_ADDRESS_MASK;
|
||||||
@@ -1019,7 +1028,7 @@ restart:
|
|||||||
struct thread* thread = thread_get_current_thread();
|
struct thread* thread = thread_get_current_thread();
|
||||||
ThreadCPUPinner pinner(thread);
|
ThreadCPUPinner pinner(thread);
|
||||||
|
|
||||||
page_table_entry* pt = fPageMapper->GetPageTableAt(
|
page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt(
|
||||||
pd[index] & X86_PDE_ADDRESS_MASK);
|
pd[index] & X86_PDE_ADDRESS_MASK);
|
||||||
|
|
||||||
for (index = VADDR_TO_PTENT(start); index < 1024 && start < end;
|
for (index = VADDR_TO_PTENT(start); index < 1024 && start < end;
|
||||||
@@ -1078,7 +1087,7 @@ X86VMTranslationMap::ClearFlags(addr_t va, uint32 flags)
|
|||||||
struct thread* thread = thread_get_current_thread();
|
struct thread* thread = thread_get_current_thread();
|
||||||
ThreadCPUPinner pinner(thread);
|
ThreadCPUPinner pinner(thread);
|
||||||
|
|
||||||
page_table_entry* pt = fPageMapper->GetPageTableAt(
|
page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt(
|
||||||
pd[index] & X86_PDE_ADDRESS_MASK);
|
pd[index] & X86_PDE_ADDRESS_MASK);
|
||||||
index = VADDR_TO_PTENT(va);
|
index = VADDR_TO_PTENT(va);
|
||||||
|
|
||||||
@@ -1118,7 +1127,7 @@ X86VMTranslationMap::ClearAccessedAndModified(VMArea* area, addr_t address,
|
|||||||
|
|
||||||
ThreadCPUPinner pinner(thread_get_current_thread());
|
ThreadCPUPinner pinner(thread_get_current_thread());
|
||||||
|
|
||||||
page_table_entry* pt = fPageMapper->GetPageTableAt(
|
page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt(
|
||||||
pd[index] & X86_PDE_ADDRESS_MASK);
|
pd[index] & X86_PDE_ADDRESS_MASK);
|
||||||
|
|
||||||
index = VADDR_TO_PTENT(address);
|
index = VADDR_TO_PTENT(address);
|
||||||
@@ -1277,6 +1286,205 @@ X86VMTranslationMap::Flush()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - X86PagingMethod32Bit::PhysicalPageSlotPool
|
||||||
|
|
||||||
|
|
||||||
|
struct X86PagingMethod32Bit::PhysicalPageSlotPool
|
||||||
|
: X86LargePhysicalPageMapper::PhysicalPageSlotPool {
|
||||||
|
public:
|
||||||
|
virtual ~PhysicalPageSlotPool();
|
||||||
|
|
||||||
|
status_t InitInitial(kernel_args* args);
|
||||||
|
status_t InitInitialPostArea(kernel_args* args);
|
||||||
|
|
||||||
|
void Init(area_id dataArea, void* data,
|
||||||
|
area_id virtualArea, addr_t virtualBase);
|
||||||
|
|
||||||
|
virtual status_t AllocatePool(
|
||||||
|
X86LargePhysicalPageMapper
|
||||||
|
::PhysicalPageSlotPool*& _pool);
|
||||||
|
virtual void Map(phys_addr_t physicalAddress,
|
||||||
|
addr_t virtualAddress);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static PhysicalPageSlotPool sInitialPhysicalPagePool;
|
||||||
|
|
||||||
|
private:
|
||||||
|
area_id fDataArea;
|
||||||
|
area_id fVirtualArea;
|
||||||
|
addr_t fVirtualBase;
|
||||||
|
page_table_entry* fPageTable;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
X86PagingMethod32Bit::PhysicalPageSlotPool
|
||||||
|
X86PagingMethod32Bit::PhysicalPageSlotPool::sInitialPhysicalPagePool;
|
||||||
|
|
||||||
|
|
||||||
|
X86PagingMethod32Bit::PhysicalPageSlotPool::~PhysicalPageSlotPool()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
X86PagingMethod32Bit::PhysicalPageSlotPool::InitInitial(kernel_args* args)
|
||||||
|
{
|
||||||
|
// We reserve more, so that we can guarantee to align the base address
|
||||||
|
// to page table ranges.
|
||||||
|
addr_t virtualBase = vm_allocate_early(args,
|
||||||
|
1024 * B_PAGE_SIZE + kPageTableAlignment - B_PAGE_SIZE, 0, 0, false);
|
||||||
|
if (virtualBase == 0) {
|
||||||
|
panic("LargeMemoryPhysicalPageMapper::Init(): Failed to reserve "
|
||||||
|
"physical page pool space in virtual address space!");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
virtualBase = (virtualBase + kPageTableAlignment - 1)
|
||||||
|
/ kPageTableAlignment * kPageTableAlignment;
|
||||||
|
|
||||||
|
// allocate memory for the page table and data
|
||||||
|
size_t areaSize = B_PAGE_SIZE + sizeof(PhysicalPageSlot[1024]);
|
||||||
|
page_table_entry* pageTable = (page_table_entry*)vm_allocate_early(args,
|
||||||
|
areaSize, ~0L, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, false);
|
||||||
|
|
||||||
|
// prepare the page table
|
||||||
|
x86_early_prepare_page_tables(pageTable, virtualBase,
|
||||||
|
1024 * B_PAGE_SIZE);
|
||||||
|
|
||||||
|
// init the pool structure and add the initial pool
|
||||||
|
Init(-1, pageTable, -1, (addr_t)virtualBase);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
X86PagingMethod32Bit::PhysicalPageSlotPool::InitInitialPostArea(
|
||||||
|
kernel_args* args)
|
||||||
|
{
|
||||||
|
// create an area for the (already allocated) data
|
||||||
|
size_t areaSize = B_PAGE_SIZE + sizeof(PhysicalPageSlot[1024]);
|
||||||
|
void* temp = fPageTable;
|
||||||
|
area_id area = create_area("physical page pool", &temp,
|
||||||
|
B_EXACT_ADDRESS, areaSize, B_ALREADY_WIRED,
|
||||||
|
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||||
|
if (area < B_OK) {
|
||||||
|
panic("LargeMemoryPhysicalPageMapper::InitPostArea(): Failed to "
|
||||||
|
"create area for physical page pool.");
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
fDataArea = area;
|
||||||
|
|
||||||
|
// create an area for the virtual address space
|
||||||
|
temp = (void*)fVirtualBase;
|
||||||
|
area = vm_create_null_area(VMAddressSpace::KernelID(),
|
||||||
|
"physical page pool space", &temp, B_EXACT_ADDRESS,
|
||||||
|
1024 * B_PAGE_SIZE, 0);
|
||||||
|
if (area < B_OK) {
|
||||||
|
panic("LargeMemoryPhysicalPageMapper::InitPostArea(): Failed to "
|
||||||
|
"create area for physical page pool space.");
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
fVirtualArea = area;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
X86PagingMethod32Bit::PhysicalPageSlotPool::Init(area_id dataArea, void* data,
|
||||||
|
area_id virtualArea, addr_t virtualBase)
|
||||||
|
{
|
||||||
|
fDataArea = dataArea;
|
||||||
|
fVirtualArea = virtualArea;
|
||||||
|
fVirtualBase = virtualBase;
|
||||||
|
fPageTable = (page_table_entry*)data;
|
||||||
|
|
||||||
|
// init slot list
|
||||||
|
fSlots = (PhysicalPageSlot*)(fPageTable + 1024);
|
||||||
|
addr_t slotAddress = virtualBase;
|
||||||
|
for (int32 i = 0; i < 1024; i++, slotAddress += B_PAGE_SIZE) {
|
||||||
|
PhysicalPageSlot* slot = &fSlots[i];
|
||||||
|
slot->next = slot + 1;
|
||||||
|
slot->pool = this;
|
||||||
|
slot->address = slotAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
fSlots[1023].next = NULL;
|
||||||
|
// terminate list
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
X86PagingMethod32Bit::PhysicalPageSlotPool::Map(phys_addr_t physicalAddress,
|
||||||
|
addr_t virtualAddress)
|
||||||
|
{
|
||||||
|
page_table_entry& pte = fPageTable[
|
||||||
|
(virtualAddress - fVirtualBase) / B_PAGE_SIZE];
|
||||||
|
pte = (physicalAddress & X86_PTE_ADDRESS_MASK)
|
||||||
|
| X86_PTE_WRITABLE | X86_PTE_GLOBAL | X86_PTE_PRESENT;
|
||||||
|
|
||||||
|
invalidate_TLB(virtualAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
X86PagingMethod32Bit::PhysicalPageSlotPool::AllocatePool(
|
||||||
|
X86LargePhysicalPageMapper::PhysicalPageSlotPool*& _pool)
|
||||||
|
{
|
||||||
|
// create the pool structure
|
||||||
|
PhysicalPageSlotPool* pool = new(std::nothrow) PhysicalPageSlotPool;
|
||||||
|
if (pool == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
ObjectDeleter<PhysicalPageSlotPool> poolDeleter(pool);
|
||||||
|
|
||||||
|
// create an area that can contain the page table and the slot
|
||||||
|
// structures
|
||||||
|
size_t areaSize = B_PAGE_SIZE + sizeof(PhysicalPageSlot[1024]);
|
||||||
|
void* data;
|
||||||
|
area_id dataArea = create_area_etc(B_SYSTEM_TEAM, "physical page pool",
|
||||||
|
&data, B_ANY_KERNEL_ADDRESS, PAGE_ALIGN(areaSize), B_FULL_LOCK,
|
||||||
|
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 0, CREATE_AREA_DONT_WAIT);
|
||||||
|
if (dataArea < 0)
|
||||||
|
return dataArea;
|
||||||
|
|
||||||
|
// create the null area for the virtual address space
|
||||||
|
void* virtualBase;
|
||||||
|
area_id virtualArea = vm_create_null_area(
|
||||||
|
VMAddressSpace::KernelID(), "physical page pool space",
|
||||||
|
&virtualBase, B_ANY_KERNEL_BLOCK_ADDRESS, 1024 * B_PAGE_SIZE,
|
||||||
|
CREATE_AREA_PRIORITY_VIP);
|
||||||
|
if (virtualArea < 0) {
|
||||||
|
delete_area(dataArea);
|
||||||
|
return virtualArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare the page table
|
||||||
|
memset(data, 0, B_PAGE_SIZE);
|
||||||
|
|
||||||
|
// get the page table's physical address
|
||||||
|
phys_addr_t physicalTable;
|
||||||
|
X86VMTranslationMap* map = static_cast<X86VMTranslationMap*>(
|
||||||
|
VMAddressSpace::Kernel()->TranslationMap());
|
||||||
|
uint32 dummyFlags;
|
||||||
|
cpu_status state = disable_interrupts();
|
||||||
|
map->QueryInterrupt((addr_t)data, &physicalTable, &dummyFlags);
|
||||||
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
// put the page table into the page directory
|
||||||
|
int32 index = (addr_t)virtualBase / (B_PAGE_SIZE * 1024);
|
||||||
|
page_directory_entry* entry = &map->PagingStructures()->pgdir_virt[index];
|
||||||
|
x86_put_pgtable_in_pgdir(entry, physicalTable,
|
||||||
|
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||||
|
x86_update_all_pgdirs(index, *entry);
|
||||||
|
|
||||||
|
// init the pool structure
|
||||||
|
pool->Init(dataArea, data, virtualArea, (addr_t)virtualBase);
|
||||||
|
poolDeleter.Detach();
|
||||||
|
_pool = pool;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - X86PagingMethod32Bit
|
// #pragma mark - X86PagingMethod32Bit
|
||||||
|
|
||||||
|
|
||||||
@@ -1326,7 +1534,19 @@ X86PagingMethod32Bit::Init(kernel_args* args,
|
|||||||
B_INITIALIZE_SPINLOCK(&sPagingStructuresListLock);
|
B_INITIALIZE_SPINLOCK(&sPagingStructuresListLock);
|
||||||
new (&sPagingStructuresList) PagingStructuresList;
|
new (&sPagingStructuresList) PagingStructuresList;
|
||||||
|
|
||||||
large_memory_physical_page_ops_init(args, sPhysicalPageMapper,
|
// create the initial pool for the physical page mapper
|
||||||
|
PhysicalPageSlotPool* pool
|
||||||
|
= new(&PhysicalPageSlotPool::sInitialPhysicalPagePool)
|
||||||
|
PhysicalPageSlotPool;
|
||||||
|
status_t error = pool->InitInitial(args);
|
||||||
|
if (error != B_OK) {
|
||||||
|
panic("X86PagingMethod32Bit::Init(): Failed to create initial pool "
|
||||||
|
"for physical page mapper!");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create physical page mapper
|
||||||
|
large_memory_physical_page_ops_init(args, pool, sPhysicalPageMapper,
|
||||||
sKernelPhysicalPageMapper);
|
sKernelPhysicalPageMapper);
|
||||||
// TODO: Select the best page mapper!
|
// TODO: Select the best page mapper!
|
||||||
|
|
||||||
@@ -1364,7 +1584,8 @@ X86PagingMethod32Bit::InitPostArea(kernel_args* args)
|
|||||||
if (area < B_OK)
|
if (area < B_OK)
|
||||||
return area;
|
return area;
|
||||||
|
|
||||||
error = sPhysicalPageMapper->InitPostArea(args);
|
error = PhysicalPageSlotPool::sInitialPhysicalPagePool
|
||||||
|
.InitInitialPostArea(args);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ public:
|
|||||||
|
|
||||||
virtual bool IsKernelPageAccessible(addr_t virtualAddress,
|
virtual bool IsKernelPageAccessible(addr_t virtualAddress,
|
||||||
uint32 protection);
|
uint32 protection);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct PhysicalPageSlotPool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
#include <vm/VMTranslationMap.h>
|
#include <vm/VMTranslationMap.h>
|
||||||
|
|
||||||
#include "x86_paging.h"
|
|
||||||
|
|
||||||
|
|
||||||
struct kernel_args;
|
struct kernel_args;
|
||||||
struct vm_translation_map_ops;
|
struct vm_translation_map_ops;
|
||||||
@@ -21,7 +19,7 @@ public:
|
|||||||
|
|
||||||
virtual void Delete() = 0;
|
virtual void Delete() = 0;
|
||||||
|
|
||||||
virtual page_table_entry* GetPageTableAt(phys_addr_t physicalAddress) = 0;
|
virtual void* GetPageTableAt(phys_addr_t physicalAddress) = 0;
|
||||||
// Must be invoked with thread pinned to current CPU.
|
// Must be invoked with thread pinned to current CPU.
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -30,20 +28,13 @@ class X86PhysicalPageMapper : public VMPhysicalPageMapper {
|
|||||||
public:
|
public:
|
||||||
virtual ~X86PhysicalPageMapper();
|
virtual ~X86PhysicalPageMapper();
|
||||||
|
|
||||||
virtual status_t InitPostArea(kernel_args* args) = 0;
|
|
||||||
|
|
||||||
virtual status_t CreateTranslationMapPhysicalPageMapper(
|
virtual status_t CreateTranslationMapPhysicalPageMapper(
|
||||||
TranslationMapPhysicalPageMapper** _mapper)
|
TranslationMapPhysicalPageMapper** _mapper)
|
||||||
= 0;
|
= 0;
|
||||||
|
|
||||||
virtual page_table_entry* InterruptGetPageTableAt(
|
virtual void* InterruptGetPageTableAt(
|
||||||
phys_addr_t physicalAddress) = 0;
|
phys_addr_t physicalAddress) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
status_t large_memory_physical_page_ops_init(kernel_args* args,
|
|
||||||
X86PhysicalPageMapper*& _pageMapper,
|
|
||||||
TranslationMapPhysicalPageMapper*& _kernelPageMapper);
|
|
||||||
|
|
||||||
|
|
||||||
#endif // _KERNEL_ARCH_X86_PHYSICAL_PAGE_MAPPER_H
|
#endif // _KERNEL_ARCH_X86_PHYSICAL_PAGE_MAPPER_H
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
We allocate a single page table (one page) that can map 1024 pages and
|
We allocate a single page table (one page) that can map 1024 pages and
|
||||||
a corresponding virtual address space region (4 MB). Each of those 1024
|
a corresponding virtual address space region (4 MB). Each of those 1024
|
||||||
slots can map a physical page. We reserve a fixed amount of slot per CPU.
|
slots can map a physical page. We reserve a fixed amount of slots per CPU.
|
||||||
They will be used for physical operations on that CPU (memset()/memcpy()
|
They will be used for physical operations on that CPU (memset()/memcpy()
|
||||||
and {get,put}_physical_page_current_cpu()). A few slots we reserve for each
|
and {get,put}_physical_page_current_cpu()). A few slots we reserve for each
|
||||||
translation map (TranslationMapPhysicalPageMapper). Those will only be used
|
translation map (TranslationMapPhysicalPageMapper). Those will only be used
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "x86_physical_page_mapper.h"
|
#include "x86_physical_page_mapper_large_memory.h"
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
@@ -33,12 +33,12 @@
|
|||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
#include <smp.h>
|
#include <smp.h>
|
||||||
#include <util/AutoLock.h>
|
#include <util/AutoLock.h>
|
||||||
#include <util/DoublyLinkedList.h>
|
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
#include <vm/vm_types.h>
|
#include <vm/vm_types.h>
|
||||||
#include <vm/VMAddressSpace.h>
|
#include <vm/VMAddressSpace.h>
|
||||||
|
|
||||||
#include "x86_paging.h"
|
#include "x86_paging.h"
|
||||||
|
#include "x86_physical_page_mapper.h"
|
||||||
#include "X86VMTranslationMap.h"
|
#include "X86VMTranslationMap.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -54,35 +54,9 @@
|
|||||||
+ KERNEL_SLOTS_PER_CPU + 1)
|
+ KERNEL_SLOTS_PER_CPU + 1)
|
||||||
// one slot is for use in interrupts
|
// one slot is for use in interrupts
|
||||||
|
|
||||||
static const size_t kPageTableAlignment = 1024 * B_PAGE_SIZE;
|
|
||||||
|
|
||||||
|
using X86LargePhysicalPageMapper::PhysicalPageSlot;
|
||||||
struct PhysicalPageSlotPool;
|
using X86LargePhysicalPageMapper::PhysicalPageSlotPool;
|
||||||
|
|
||||||
struct PhysicalPageSlot {
|
|
||||||
PhysicalPageSlot* next;
|
|
||||||
PhysicalPageSlotPool* pool;
|
|
||||||
addr_t address;
|
|
||||||
|
|
||||||
inline void Map(phys_addr_t physicalAddress);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct PhysicalPageSlotPool : DoublyLinkedListLinkImpl<PhysicalPageSlotPool> {
|
|
||||||
area_id dataArea;
|
|
||||||
area_id virtualArea;
|
|
||||||
addr_t virtualBase;
|
|
||||||
page_table_entry* pageTable;
|
|
||||||
PhysicalPageSlot* slots;
|
|
||||||
|
|
||||||
void Init(area_id dataArea, void* data,
|
|
||||||
area_id virtualArea, addr_t virtualBase);
|
|
||||||
|
|
||||||
inline bool IsEmpty() const;
|
|
||||||
|
|
||||||
inline PhysicalPageSlot* GetSlot();
|
|
||||||
inline void PutSlot(PhysicalPageSlot* slot);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class PhysicalPageSlotQueue {
|
class PhysicalPageSlotQueue {
|
||||||
@@ -131,7 +105,7 @@ public:
|
|||||||
|
|
||||||
virtual void Delete();
|
virtual void Delete();
|
||||||
|
|
||||||
virtual page_table_entry* GetPageTableAt(phys_addr_t physicalAddress);
|
virtual void* GetPageTableAt(phys_addr_t physicalAddress);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct page_slot {
|
struct page_slot {
|
||||||
@@ -151,14 +125,14 @@ public:
|
|||||||
LargeMemoryPhysicalPageMapper();
|
LargeMemoryPhysicalPageMapper();
|
||||||
|
|
||||||
status_t Init(kernel_args* args,
|
status_t Init(kernel_args* args,
|
||||||
|
PhysicalPageSlotPool* initialPool,
|
||||||
TranslationMapPhysicalPageMapper*&
|
TranslationMapPhysicalPageMapper*&
|
||||||
_kernelPageMapper);
|
_kernelPageMapper);
|
||||||
virtual status_t InitPostArea(kernel_args* args);
|
|
||||||
|
|
||||||
virtual status_t CreateTranslationMapPhysicalPageMapper(
|
virtual status_t CreateTranslationMapPhysicalPageMapper(
|
||||||
TranslationMapPhysicalPageMapper** _mapper);
|
TranslationMapPhysicalPageMapper** _mapper);
|
||||||
|
|
||||||
virtual page_table_entry* InterruptGetPageTableAt(
|
virtual void* InterruptGetPageTableAt(
|
||||||
phys_addr_t physicalAddress);
|
phys_addr_t physicalAddress);
|
||||||
|
|
||||||
virtual status_t GetPage(phys_addr_t physicalAddress,
|
virtual status_t GetPage(phys_addr_t physicalAddress,
|
||||||
@@ -190,10 +164,6 @@ public:
|
|||||||
|
|
||||||
inline PhysicalPageSlotQueue* GetSlotQueue(int32 cpu, bool user);
|
inline PhysicalPageSlotQueue* GetSlotQueue(int32 cpu, bool user);
|
||||||
|
|
||||||
private:
|
|
||||||
static status_t _AllocatePool(
|
|
||||||
PhysicalPageSlotPool*& _pool);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef DoublyLinkedList<PhysicalPageSlotPool> PoolList;
|
typedef DoublyLinkedList<PhysicalPageSlotPool> PoolList;
|
||||||
|
|
||||||
@@ -201,7 +171,7 @@ private:
|
|||||||
PoolList fEmptyPools;
|
PoolList fEmptyPools;
|
||||||
PoolList fNonEmptyPools;
|
PoolList fNonEmptyPools;
|
||||||
PhysicalPageSlot* fDebugSlot;
|
PhysicalPageSlot* fDebugSlot;
|
||||||
PhysicalPageSlotPool fInitialPool;
|
PhysicalPageSlotPool* fInitialPool;
|
||||||
LargeMemoryTranslationMapPhysicalPageMapper fKernelMapper;
|
LargeMemoryTranslationMapPhysicalPageMapper fKernelMapper;
|
||||||
PhysicalPageOpsCPUData fPerCPUData[B_MAX_CPU_COUNT];
|
PhysicalPageOpsCPUData fPerCPUData[B_MAX_CPU_COUNT];
|
||||||
};
|
};
|
||||||
@@ -215,51 +185,27 @@ static LargeMemoryPhysicalPageMapper sPhysicalPageMapper;
|
|||||||
inline void
|
inline void
|
||||||
PhysicalPageSlot::Map(phys_addr_t physicalAddress)
|
PhysicalPageSlot::Map(phys_addr_t physicalAddress)
|
||||||
{
|
{
|
||||||
page_table_entry& pte = pool->pageTable[
|
pool->Map(physicalAddress, address);
|
||||||
(address - pool->virtualBase) / B_PAGE_SIZE];
|
|
||||||
pte = (physicalAddress & X86_PTE_ADDRESS_MASK)
|
|
||||||
| X86_PTE_WRITABLE | X86_PTE_GLOBAL | X86_PTE_PRESENT;
|
|
||||||
|
|
||||||
invalidate_TLB(address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
PhysicalPageSlotPool::~PhysicalPageSlotPool()
|
||||||
PhysicalPageSlotPool::Init(area_id dataArea, void* data,
|
|
||||||
area_id virtualArea, addr_t virtualBase)
|
|
||||||
{
|
{
|
||||||
this->dataArea = dataArea;
|
|
||||||
this->virtualArea = virtualArea;
|
|
||||||
this->virtualBase = virtualBase;
|
|
||||||
pageTable = (page_table_entry*)data;
|
|
||||||
|
|
||||||
// init slot list
|
|
||||||
slots = (PhysicalPageSlot*)(pageTable + 1024);
|
|
||||||
addr_t slotAddress = virtualBase;
|
|
||||||
for (int32 i = 0; i < 1024; i++, slotAddress += B_PAGE_SIZE) {
|
|
||||||
PhysicalPageSlot* slot = &slots[i];
|
|
||||||
slot->next = slot + 1;
|
|
||||||
slot->pool = this;
|
|
||||||
slot->address = slotAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
slots[1023].next = NULL;
|
|
||||||
// terminate list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
PhysicalPageSlotPool::IsEmpty() const
|
PhysicalPageSlotPool::IsEmpty() const
|
||||||
{
|
{
|
||||||
return slots == NULL;
|
return fSlots == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline PhysicalPageSlot*
|
inline PhysicalPageSlot*
|
||||||
PhysicalPageSlotPool::GetSlot()
|
PhysicalPageSlotPool::GetSlot()
|
||||||
{
|
{
|
||||||
PhysicalPageSlot* slot = slots;
|
PhysicalPageSlot* slot = fSlots;
|
||||||
slots = slot->next;
|
fSlots = slot->next;
|
||||||
return slot;
|
return slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,8 +213,8 @@ PhysicalPageSlotPool::GetSlot()
|
|||||||
inline void
|
inline void
|
||||||
PhysicalPageSlotPool::PutSlot(PhysicalPageSlot* slot)
|
PhysicalPageSlotPool::PutSlot(PhysicalPageSlot* slot)
|
||||||
{
|
{
|
||||||
slot->next = slots;
|
slot->next = fSlots;
|
||||||
slots = slot;
|
fSlots = slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -435,7 +381,7 @@ LargeMemoryTranslationMapPhysicalPageMapper::Delete()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
page_table_entry*
|
void*
|
||||||
LargeMemoryTranslationMapPhysicalPageMapper::GetPageTableAt(
|
LargeMemoryTranslationMapPhysicalPageMapper::GetPageTableAt(
|
||||||
phys_addr_t physicalAddress)
|
phys_addr_t physicalAddress)
|
||||||
{
|
{
|
||||||
@@ -453,7 +399,7 @@ LargeMemoryTranslationMapPhysicalPageMapper::GetPageTableAt(
|
|||||||
invalidate_TLB(slot.slot->address);
|
invalidate_TLB(slot.slot->address);
|
||||||
slot.valid |= 1 << currentCPU;
|
slot.valid |= 1 << currentCPU;
|
||||||
}
|
}
|
||||||
return (page_table_entry*)slot.slot->address;
|
return (void*)slot.slot->address;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,7 +411,7 @@ LargeMemoryTranslationMapPhysicalPageMapper::GetPageTableAt(
|
|||||||
slot.slot->Map(physicalAddress);
|
slot.slot->Map(physicalAddress);
|
||||||
slot.valid = 1 << currentCPU;
|
slot.valid = 1 << currentCPU;
|
||||||
|
|
||||||
return (page_table_entry*)slot.slot->address;
|
return (void*)slot.slot->address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -473,6 +419,8 @@ LargeMemoryTranslationMapPhysicalPageMapper::GetPageTableAt(
|
|||||||
|
|
||||||
|
|
||||||
LargeMemoryPhysicalPageMapper::LargeMemoryPhysicalPageMapper()
|
LargeMemoryPhysicalPageMapper::LargeMemoryPhysicalPageMapper()
|
||||||
|
:
|
||||||
|
fInitialPool(NULL)
|
||||||
{
|
{
|
||||||
mutex_init(&fLock, "large memory physical page mapper");
|
mutex_init(&fLock, "large memory physical page mapper");
|
||||||
}
|
}
|
||||||
@@ -480,32 +428,11 @@ LargeMemoryPhysicalPageMapper::LargeMemoryPhysicalPageMapper()
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
LargeMemoryPhysicalPageMapper::Init(kernel_args* args,
|
LargeMemoryPhysicalPageMapper::Init(kernel_args* args,
|
||||||
|
PhysicalPageSlotPool* initialPool,
|
||||||
TranslationMapPhysicalPageMapper*& _kernelPageMapper)
|
TranslationMapPhysicalPageMapper*& _kernelPageMapper)
|
||||||
{
|
{
|
||||||
// We reserve more, so that we can guarantee to align the base address
|
fInitialPool = initialPool;
|
||||||
// to page table ranges.
|
fNonEmptyPools.Add(fInitialPool);
|
||||||
addr_t virtualBase = vm_allocate_early(args,
|
|
||||||
1024 * B_PAGE_SIZE + kPageTableAlignment - B_PAGE_SIZE, 0, 0, false);
|
|
||||||
if (virtualBase == 0) {
|
|
||||||
panic("LargeMemoryPhysicalPageMapper::Init(): Failed to reserve "
|
|
||||||
"physical page pool space in virtual address space!");
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
virtualBase = (virtualBase + kPageTableAlignment - 1)
|
|
||||||
/ kPageTableAlignment * kPageTableAlignment;
|
|
||||||
|
|
||||||
// allocate memory for the page table and data
|
|
||||||
size_t areaSize = B_PAGE_SIZE + sizeof(PhysicalPageSlot[1024]);
|
|
||||||
page_table_entry* pageTable = (page_table_entry*)vm_allocate_early(args,
|
|
||||||
areaSize, ~0L, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, false);
|
|
||||||
|
|
||||||
// prepare the page table
|
|
||||||
x86_early_prepare_page_tables(pageTable, virtualBase,
|
|
||||||
1024 * B_PAGE_SIZE);
|
|
||||||
|
|
||||||
// init the pool structure and add the initial pool
|
|
||||||
fInitialPool.Init(-1, pageTable, -1, (addr_t)virtualBase);
|
|
||||||
fNonEmptyPools.Add(&fInitialPool);
|
|
||||||
|
|
||||||
// get the debug slot
|
// get the debug slot
|
||||||
GetSlot(true, fDebugSlot);
|
GetSlot(true, fDebugSlot);
|
||||||
@@ -528,38 +455,6 @@ LargeMemoryPhysicalPageMapper::Init(kernel_args* args,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
LargeMemoryPhysicalPageMapper::InitPostArea(kernel_args* args)
|
|
||||||
{
|
|
||||||
// create an area for the (already allocated) data
|
|
||||||
size_t areaSize = B_PAGE_SIZE + sizeof(PhysicalPageSlot[1024]);
|
|
||||||
void* temp = fInitialPool.pageTable;
|
|
||||||
area_id area = create_area("physical page pool", &temp,
|
|
||||||
B_EXACT_ADDRESS, areaSize, B_ALREADY_WIRED,
|
|
||||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
|
||||||
if (area < B_OK) {
|
|
||||||
panic("LargeMemoryPhysicalPageMapper::InitPostArea(): Failed to "
|
|
||||||
"create area for physical page pool.");
|
|
||||||
return area;
|
|
||||||
}
|
|
||||||
fInitialPool.dataArea = area;
|
|
||||||
|
|
||||||
// create an area for the virtual address space
|
|
||||||
temp = (void*)fInitialPool.virtualBase;
|
|
||||||
area = vm_create_null_area(VMAddressSpace::KernelID(),
|
|
||||||
"physical page pool space", &temp, B_EXACT_ADDRESS,
|
|
||||||
1024 * B_PAGE_SIZE, 0);
|
|
||||||
if (area < B_OK) {
|
|
||||||
panic("LargeMemoryPhysicalPageMapper::InitPostArea(): Failed to "
|
|
||||||
"create area for physical page pool space.");
|
|
||||||
return area;
|
|
||||||
}
|
|
||||||
fInitialPool.virtualArea = area;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
LargeMemoryPhysicalPageMapper::CreateTranslationMapPhysicalPageMapper(
|
LargeMemoryPhysicalPageMapper::CreateTranslationMapPhysicalPageMapper(
|
||||||
TranslationMapPhysicalPageMapper** _mapper)
|
TranslationMapPhysicalPageMapper** _mapper)
|
||||||
@@ -580,7 +475,7 @@ LargeMemoryPhysicalPageMapper::CreateTranslationMapPhysicalPageMapper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
page_table_entry*
|
void*
|
||||||
LargeMemoryPhysicalPageMapper::InterruptGetPageTableAt(
|
LargeMemoryPhysicalPageMapper::InterruptGetPageTableAt(
|
||||||
phys_addr_t physicalAddress)
|
phys_addr_t physicalAddress)
|
||||||
{
|
{
|
||||||
@@ -588,7 +483,7 @@ LargeMemoryPhysicalPageMapper::InterruptGetPageTableAt(
|
|||||||
|
|
||||||
PhysicalPageSlot* slot = fPerCPUData[smp_get_current_cpu()].interruptSlot;
|
PhysicalPageSlot* slot = fPerCPUData[smp_get_current_cpu()].interruptSlot;
|
||||||
slot->Map(physicalAddress);
|
slot->Map(physicalAddress);
|
||||||
return (page_table_entry*)slot->address;
|
return (void*)slot->address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -802,8 +697,7 @@ LargeMemoryPhysicalPageMapper::MemcpyPhysicalPage(phys_addr_t to,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
LargeMemoryPhysicalPageMapper::GetSlot(bool canWait,
|
LargeMemoryPhysicalPageMapper::GetSlot(bool canWait, PhysicalPageSlot*& slot)
|
||||||
PhysicalPageSlot*& slot)
|
|
||||||
{
|
{
|
||||||
MutexLocker locker(fLock);
|
MutexLocker locker(fLock);
|
||||||
|
|
||||||
@@ -814,7 +708,7 @@ LargeMemoryPhysicalPageMapper::GetSlot(bool canWait,
|
|||||||
|
|
||||||
// allocate new pool
|
// allocate new pool
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
status_t error = _AllocatePool(pool);
|
status_t error = fInitialPool->AllocatePool(pool);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
locker.Lock();
|
locker.Lock();
|
||||||
@@ -856,74 +750,17 @@ LargeMemoryPhysicalPageMapper::GetSlotQueue(int32 cpu, bool user)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* static */ status_t
|
|
||||||
LargeMemoryPhysicalPageMapper::_AllocatePool(PhysicalPageSlotPool*& _pool)
|
|
||||||
{
|
|
||||||
// create the pool structure
|
|
||||||
PhysicalPageSlotPool* pool
|
|
||||||
= new(std::nothrow) PhysicalPageSlotPool;
|
|
||||||
if (pool == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
ObjectDeleter<PhysicalPageSlotPool> poolDeleter(pool);
|
|
||||||
|
|
||||||
// create an area that can contain the page table and the slot
|
|
||||||
// structures
|
|
||||||
size_t areaSize = B_PAGE_SIZE + sizeof(PhysicalPageSlot[1024]);
|
|
||||||
void* data;
|
|
||||||
area_id dataArea = create_area_etc(B_SYSTEM_TEAM, "physical page pool",
|
|
||||||
&data, B_ANY_KERNEL_ADDRESS, PAGE_ALIGN(areaSize), B_FULL_LOCK,
|
|
||||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 0, CREATE_AREA_DONT_WAIT);
|
|
||||||
if (dataArea < 0)
|
|
||||||
return dataArea;
|
|
||||||
|
|
||||||
// create the null area for the virtual address space
|
|
||||||
void* virtualBase;
|
|
||||||
area_id virtualArea = vm_create_null_area(
|
|
||||||
VMAddressSpace::KernelID(), "physical page pool space",
|
|
||||||
&virtualBase, B_ANY_KERNEL_BLOCK_ADDRESS, 1024 * B_PAGE_SIZE,
|
|
||||||
CREATE_AREA_PRIORITY_VIP);
|
|
||||||
if (virtualArea < 0) {
|
|
||||||
delete_area(dataArea);
|
|
||||||
return virtualArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepare the page table
|
|
||||||
memset(data, 0, B_PAGE_SIZE);
|
|
||||||
|
|
||||||
// get the page table's physical address
|
|
||||||
phys_addr_t physicalTable;
|
|
||||||
X86VMTranslationMap* map = static_cast<X86VMTranslationMap*>(
|
|
||||||
VMAddressSpace::Kernel()->TranslationMap());
|
|
||||||
uint32 dummyFlags;
|
|
||||||
cpu_status state = disable_interrupts();
|
|
||||||
map->QueryInterrupt((addr_t)data, &physicalTable, &dummyFlags);
|
|
||||||
restore_interrupts(state);
|
|
||||||
|
|
||||||
// put the page table into the page directory
|
|
||||||
int32 index = (addr_t)virtualBase / (B_PAGE_SIZE * 1024);
|
|
||||||
page_directory_entry* entry = &map->PagingStructures()->pgdir_virt[index];
|
|
||||||
x86_put_pgtable_in_pgdir(entry, physicalTable,
|
|
||||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
|
||||||
x86_update_all_pgdirs(index, *entry);
|
|
||||||
|
|
||||||
// init the pool structure
|
|
||||||
pool->Init(dataArea, data, virtualArea, (addr_t)virtualBase);
|
|
||||||
poolDeleter.Detach();
|
|
||||||
_pool = pool;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Initialization
|
// #pragma mark - Initialization
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
large_memory_physical_page_ops_init(kernel_args* args,
|
large_memory_physical_page_ops_init(kernel_args* args,
|
||||||
|
X86LargePhysicalPageMapper::PhysicalPageSlotPool* initialPool,
|
||||||
X86PhysicalPageMapper*& _pageMapper,
|
X86PhysicalPageMapper*& _pageMapper,
|
||||||
TranslationMapPhysicalPageMapper*& _kernelPageMapper)
|
TranslationMapPhysicalPageMapper*& _kernelPageMapper)
|
||||||
{
|
{
|
||||||
new(&sPhysicalPageMapper) LargeMemoryPhysicalPageMapper;
|
new(&sPhysicalPageMapper) LargeMemoryPhysicalPageMapper;
|
||||||
sPhysicalPageMapper.Init(args, _kernelPageMapper);
|
sPhysicalPageMapper.Init(args, initialPool, _kernelPageMapper);
|
||||||
|
|
||||||
_pageMapper = &sPhysicalPageMapper;
|
_pageMapper = &sPhysicalPageMapper;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef KERNEL_ARCH_X86_X86_PHYSICAL_PAGE_MAPPER_LARGE_MEMORY_H
|
||||||
|
#define KERNEL_ARCH_X86_X86_PHYSICAL_PAGE_MAPPER_LARGE_MEMORY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
|
class TranslationMapPhysicalPageMapper;
|
||||||
|
class X86PhysicalPageMapper;
|
||||||
|
struct kernel_args;
|
||||||
|
|
||||||
|
|
||||||
|
namespace X86LargePhysicalPageMapper {
|
||||||
|
|
||||||
|
|
||||||
|
struct PhysicalPageSlotPool;
|
||||||
|
|
||||||
|
|
||||||
|
struct PhysicalPageSlot {
|
||||||
|
PhysicalPageSlot* next;
|
||||||
|
PhysicalPageSlotPool* pool;
|
||||||
|
addr_t address;
|
||||||
|
|
||||||
|
inline void Map(phys_addr_t physicalAddress);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct PhysicalPageSlotPool : DoublyLinkedListLinkImpl<PhysicalPageSlotPool> {
|
||||||
|
|
||||||
|
virtual ~PhysicalPageSlotPool();
|
||||||
|
|
||||||
|
inline bool IsEmpty() const;
|
||||||
|
|
||||||
|
inline PhysicalPageSlot* GetSlot();
|
||||||
|
inline void PutSlot(PhysicalPageSlot* slot);
|
||||||
|
|
||||||
|
virtual status_t AllocatePool(PhysicalPageSlotPool*& _pool) = 0;
|
||||||
|
virtual void Map(phys_addr_t physicalAddress,
|
||||||
|
addr_t virtualAddress) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PhysicalPageSlot* fSlots;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t large_memory_physical_page_ops_init(kernel_args* args,
|
||||||
|
X86LargePhysicalPageMapper::PhysicalPageSlotPool* initialPool,
|
||||||
|
X86PhysicalPageMapper*& _pageMapper,
|
||||||
|
TranslationMapPhysicalPageMapper*& _kernelPageMapper);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // KERNEL_ARCH_X86_X86_PHYSICAL_PAGE_MAPPER_LARGE_MEMORY_H
|
||||||
Reference in New Issue
Block a user