[haiku-commits] r37054 - haiku/trunk/src/system/kernel/arch/x86

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 8 Jun 2010 01:11:02 +0200 (CEST)

Author: bonefish
Date: 2010-06-08 01:11:01 +0200 (Tue, 08 Jun 2010)
New Revision: 37054
Changeset: http://dev.haiku-os.org/changeset/37054/haiku

Added:
   
haiku/trunk/src/system/kernel/arch/x86/x86_physical_page_mapper_large_memory.h
Modified:
   haiku/trunk/src/system/kernel/arch/x86/X86PagingMethod32Bit.cpp
   haiku/trunk/src/system/kernel/arch/x86/X86PagingMethod32Bit.h
   haiku/trunk/src/system/kernel/arch/x86/x86_physical_page_mapper.h
   
haiku/trunk/src/system/kernel/arch/x86/x86_physical_page_mapper_large_memory.cpp
Log:
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.


Modified: haiku/trunk/src/system/kernel/arch/x86/X86PagingMethod32Bit.cpp
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/X86PagingMethod32Bit.cpp     
2010-06-07 22:14:16 UTC (rev 37053)
+++ haiku/trunk/src/system/kernel/arch/x86/X86PagingMethod32Bit.cpp     
2010-06-07 23:11:01 UTC (rev 37054)
@@ -29,6 +29,7 @@
 #include <vm/VMCache.h>
 
 #include "x86_physical_page_mapper.h"
+#include "x86_physical_page_mapper_large_memory.h"
 #include "X86VMTranslationMap.h"
 
 
@@ -40,6 +41,12 @@
 #endif
 
 
+using X86LargePhysicalPageMapper::PhysicalPageSlot;
+
+
+static const size_t kPageTableAlignment = 1024 * B_PAGE_SIZE;
+
+
 static X86PagingMethod32Bit sMethod;
 
 static page_table_entry *sPageHole = NULL;
@@ -474,7 +481,7 @@
        struct thread* thread = thread_get_current_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);
        index = VADDR_TO_PTENT(va);
 
@@ -522,7 +529,7 @@
        struct thread* thread = thread_get_current_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);
 
        for (index = VADDR_TO_PTENT(start); (index < 1024) && (start < end);
@@ -576,7 +583,7 @@
 
        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);
 
        index = VADDR_TO_PTENT(address);
@@ -700,7 +707,7 @@
                struct thread* thread = thread_get_current_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);
 
                for (index = VADDR_TO_PTENT(start); (index < 1024) && (start < 
end);
@@ -837,8 +844,9 @@
 
                        ThreadCPUPinner pinner(thread_get_current_thread());
 
-                       page_table_entry* pt = fPageMapper->GetPageTableAt(
-                               pd[index] & X86_PDE_ADDRESS_MASK);
+                       page_table_entry* pt
+                               = 
(page_table_entry*)fPageMapper->GetPageTableAt(
+                                       pd[index] & X86_PDE_ADDRESS_MASK);
                        page_table_entry oldEntry = clear_page_table_entry(
                                &pt[VADDR_TO_PTENT(address)]);
 
@@ -913,7 +921,7 @@
        struct thread* thread = thread_get_current_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);
        page_table_entry entry = pt[VADDR_TO_PTENT(va)];
 
@@ -954,8 +962,9 @@
        }
 
        // map page table entry
-       page_table_entry* pt = sPhysicalPageMapper->InterruptGetPageTableAt(
-               pd[index] & X86_PDE_ADDRESS_MASK);
+       page_table_entry* pt
+               = 
(page_table_entry*)sPhysicalPageMapper->InterruptGetPageTableAt(
+                       pd[index] & X86_PDE_ADDRESS_MASK);
        page_table_entry entry = pt[VADDR_TO_PTENT(va)];
 
        *_physical = entry & X86_PDE_ADDRESS_MASK;
@@ -1019,7 +1028,7 @@
        struct thread* thread = thread_get_current_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);
 
        for (index = VADDR_TO_PTENT(start); index < 1024 && start < end;
@@ -1078,7 +1087,7 @@
        struct thread* thread = thread_get_current_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);
        index = VADDR_TO_PTENT(va);
 
@@ -1118,7 +1127,7 @@
 
        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);
 
        index = VADDR_TO_PTENT(address);
@@ -1277,6 +1286,205 @@
 }
 
 
+// #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
 
 
@@ -1326,7 +1534,19 @@
        B_INITIALIZE_SPINLOCK(&sPagingStructuresListLock);
        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);
                // TODO: Select the best page mapper!
 
@@ -1364,7 +1584,8 @@
        if (area < B_OK)
                return area;
 
-       error = sPhysicalPageMapper->InitPostArea(args);
+       error = PhysicalPageSlotPool::sInitialPhysicalPagePool
+               .InitInitialPostArea(args);
        if (error != B_OK)
                return error;
 

Modified: haiku/trunk/src/system/kernel/arch/x86/X86PagingMethod32Bit.h
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/X86PagingMethod32Bit.h       
2010-06-07 22:14:16 UTC (rev 37053)
+++ haiku/trunk/src/system/kernel/arch/x86/X86PagingMethod32Bit.h       
2010-06-07 23:11:01 UTC (rev 37054)
@@ -40,6 +40,9 @@
 
        virtual bool                            IsKernelPageAccessible(addr_t 
virtualAddress,
                                                                        uint32 
protection);
+
+private:
+                       struct PhysicalPageSlotPool;
 };
 
 

Modified: haiku/trunk/src/system/kernel/arch/x86/x86_physical_page_mapper.h
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/x86_physical_page_mapper.h   
2010-06-07 22:14:16 UTC (rev 37053)
+++ haiku/trunk/src/system/kernel/arch/x86/x86_physical_page_mapper.h   
2010-06-07 23:11:01 UTC (rev 37054)
@@ -8,9 +8,7 @@
 
 #include <vm/VMTranslationMap.h>
 
-#include "x86_paging.h"
 
-
 struct kernel_args;
 struct vm_translation_map_ops;
 
@@ -21,7 +19,7 @@
 
        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.
 };
 
@@ -30,20 +28,13 @@
 public:
        virtual                                         
~X86PhysicalPageMapper();
 
-       virtual status_t                        InitPostArea(kernel_args* args) 
= 0;
-
        virtual status_t                        
CreateTranslationMapPhysicalPageMapper(
                                                                        
TranslationMapPhysicalPageMapper** _mapper)
                                                                                
= 0;
 
-       virtual page_table_entry*       InterruptGetPageTableAt(
+       virtual void*                           InterruptGetPageTableAt(
                                                                        
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

Modified: 
haiku/trunk/src/system/kernel/arch/x86/x86_physical_page_mapper_large_memory.cpp
===================================================================
--- 
haiku/trunk/src/system/kernel/arch/x86/x86_physical_page_mapper_large_memory.cpp
    2010-06-07 22:14:16 UTC (rev 37053)
+++ 
haiku/trunk/src/system/kernel/arch/x86/x86_physical_page_mapper_large_memory.cpp
    2010-06-07 23:11:01 UTC (rev 37054)
@@ -11,7 +11,7 @@
 
        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
-       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()
        and {get,put}_physical_page_current_cpu()). A few slots we reserve for 
each
        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>
 
@@ -33,12 +33,12 @@
 #include <lock.h>
 #include <smp.h>
 #include <util/AutoLock.h>
-#include <util/DoublyLinkedList.h>
 #include <vm/vm.h>
 #include <vm/vm_types.h>
 #include <vm/VMAddressSpace.h>
 
 #include "x86_paging.h"
+#include "x86_physical_page_mapper.h"
 #include "X86VMTranslationMap.h"
 
 
@@ -54,37 +54,11 @@
                                                                                
        + KERNEL_SLOTS_PER_CPU + 1)
        // one slot is for use in interrupts
 
-static const size_t kPageTableAlignment = 1024 * B_PAGE_SIZE;
 
+using X86LargePhysicalPageMapper::PhysicalPageSlot;
+using X86LargePhysicalPageMapper::PhysicalPageSlotPool;
 
-struct 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 {
 public:
                                                                
PhysicalPageSlotQueue();
@@ -131,7 +105,7 @@
 
        virtual void                            Delete();
 
-       virtual page_table_entry*       GetPageTableAt(phys_addr_t 
physicalAddress);
+       virtual void*                           GetPageTableAt(phys_addr_t 
physicalAddress);
 
 private:
                        struct page_slot {
@@ -151,14 +125,14 @@
                                                                
LargeMemoryPhysicalPageMapper();
 
                        status_t                        Init(kernel_args* args,
+                                                                        
PhysicalPageSlotPool* initialPool,
                                                                         
TranslationMapPhysicalPageMapper*&
                                                                                
_kernelPageMapper);
-       virtual status_t                        InitPostArea(kernel_args* args);
 
        virtual status_t                        
CreateTranslationMapPhysicalPageMapper(
                                                                        
TranslationMapPhysicalPageMapper** _mapper);
 
-       virtual page_table_entry*       InterruptGetPageTableAt(
+       virtual void*                           InterruptGetPageTableAt(
                                                                        
phys_addr_t physicalAddress);
 
        virtual status_t                        GetPage(phys_addr_t 
physicalAddress,
@@ -191,17 +165,13 @@
        inline  PhysicalPageSlotQueue* GetSlotQueue(int32 cpu, bool user);
 
 private:
-       static  status_t                        _AllocatePool(
-                                                                       
PhysicalPageSlotPool*& _pool);
-
-private:
        typedef DoublyLinkedList<PhysicalPageSlotPool> PoolList;
 
                        mutex                           fLock;
                        PoolList                        fEmptyPools;
                        PoolList                        fNonEmptyPools;
                        PhysicalPageSlot* fDebugSlot;
-                       PhysicalPageSlotPool fInitialPool;
+                       PhysicalPageSlotPool* fInitialPool;
                        LargeMemoryTranslationMapPhysicalPageMapper     
fKernelMapper;
                        PhysicalPageOpsCPUData fPerCPUData[B_MAX_CPU_COUNT];
 };
@@ -215,51 +185,27 @@
 inline void
 PhysicalPageSlot::Map(phys_addr_t physicalAddress)
 {
-       page_table_entry& pte = pool->pageTable[
-               (address - pool->virtualBase) / B_PAGE_SIZE];
-       pte = (physicalAddress & X86_PTE_ADDRESS_MASK)
-               | X86_PTE_WRITABLE | X86_PTE_GLOBAL | X86_PTE_PRESENT;
-
-       invalidate_TLB(address);
+       pool->Map(physicalAddress, address);
 }
 
 
-void
-PhysicalPageSlotPool::Init(area_id dataArea, void* data,
-       area_id virtualArea, addr_t virtualBase)
+PhysicalPageSlotPool::~PhysicalPageSlotPool()
 {
-       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
 PhysicalPageSlotPool::IsEmpty() const
 {
-       return slots == NULL;
+       return fSlots == NULL;
 }
 
 
 inline PhysicalPageSlot*
 PhysicalPageSlotPool::GetSlot()
 {
-       PhysicalPageSlot* slot = slots;
-       slots = slot->next;
+       PhysicalPageSlot* slot = fSlots;
+       fSlots = slot->next;
        return slot;
 }
 
@@ -267,8 +213,8 @@
 inline void
 PhysicalPageSlotPool::PutSlot(PhysicalPageSlot* slot)
 {
-       slot->next = slots;
-       slots = slot;
+       slot->next = fSlots;
+       fSlots = slot;
 }
 
 
@@ -435,7 +381,7 @@
 }
 
 
-page_table_entry*
+void*
 LargeMemoryTranslationMapPhysicalPageMapper::GetPageTableAt(
        phys_addr_t physicalAddress)
 {
@@ -453,7 +399,7 @@
                                invalidate_TLB(slot.slot->address);
                                slot.valid |= 1 << currentCPU;
                        }
-                       return (page_table_entry*)slot.slot->address;
+                       return (void*)slot.slot->address;
                }
        }
 
@@ -465,7 +411,7 @@
        slot.slot->Map(physicalAddress);
        slot.valid = 1 << currentCPU;
 
-       return (page_table_entry*)slot.slot->address;
+       return (void*)slot.slot->address;
 }
 
 
@@ -473,6 +419,8 @@
 
 
 LargeMemoryPhysicalPageMapper::LargeMemoryPhysicalPageMapper()
+       :
+       fInitialPool(NULL)
 {
        mutex_init(&fLock, "large memory physical page mapper");
 }
@@ -480,33 +428,12 @@
 
 status_t
 LargeMemoryPhysicalPageMapper::Init(kernel_args* args,
+       PhysicalPageSlotPool* initialPool,
        TranslationMapPhysicalPageMapper*& _kernelPageMapper)
 {
-       // 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;
+       fInitialPool = initialPool;
+       fNonEmptyPools.Add(fInitialPool);
 
-       // 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
        GetSlot(true, fDebugSlot);
 
@@ -529,38 +456,6 @@
 
 
 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
 LargeMemoryPhysicalPageMapper::CreateTranslationMapPhysicalPageMapper(
        TranslationMapPhysicalPageMapper** _mapper)
 {
@@ -580,7 +475,7 @@
 }
 
 
-page_table_entry*
+void*
 LargeMemoryPhysicalPageMapper::InterruptGetPageTableAt(
        phys_addr_t physicalAddress)
 {
@@ -588,7 +483,7 @@
 
        PhysicalPageSlot* slot = 
fPerCPUData[smp_get_current_cpu()].interruptSlot;
        slot->Map(physicalAddress);
-       return (page_table_entry*)slot->address;
+       return (void*)slot->address;
 }
 
 
@@ -802,8 +697,7 @@
 
 
 status_t
-LargeMemoryPhysicalPageMapper::GetSlot(bool canWait,
-       PhysicalPageSlot*& slot)
+LargeMemoryPhysicalPageMapper::GetSlot(bool canWait, PhysicalPageSlot*& slot)
 {
        MutexLocker locker(fLock);
 
@@ -814,7 +708,7 @@
 
                // allocate new pool
                locker.Unlock();
-               status_t error = _AllocatePool(pool);
+               status_t error = fInitialPool->AllocatePool(pool);
                if (error != B_OK)
                        return error;
                locker.Lock();
@@ -856,74 +750,17 @@
 }
 
 
-/* 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
 
 
 status_t
 large_memory_physical_page_ops_init(kernel_args* args,
+       X86LargePhysicalPageMapper::PhysicalPageSlotPool* initialPool,
        X86PhysicalPageMapper*& _pageMapper,
        TranslationMapPhysicalPageMapper*& _kernelPageMapper)
 {
        new(&sPhysicalPageMapper) LargeMemoryPhysicalPageMapper;
-       sPhysicalPageMapper.Init(args, _kernelPageMapper);
+       sPhysicalPageMapper.Init(args, initialPool, _kernelPageMapper);
 
        _pageMapper = &sPhysicalPageMapper;
        return B_OK;

Added: 
haiku/trunk/src/system/kernel/arch/x86/x86_physical_page_mapper_large_memory.h
===================================================================
--- 
haiku/trunk/src/system/kernel/arch/x86/x86_physical_page_mapper_large_memory.h  
                            (rev 0)
+++ 
haiku/trunk/src/system/kernel/arch/x86/x86_physical_page_mapper_large_memory.h  
    2010-06-07 23:11:01 UTC (rev 37054)
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * 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


Other related posts:

  • » [haiku-commits] r37054 - haiku/trunk/src/system/kernel/arch/x86 - ingo_weinhold