From 68b53104ba4f01a0399a1a32710388faf3805d4d Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Fri, 11 Jun 2010 16:21:13 +0000 Subject: [PATCH] * Implemented X86VMTranslationMapPAE and X86PagingStructuresPAE destruction. * Implemented X86VMTranslationMapPAE::QueryInterrupt(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37100 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../x86/paging/pae/X86PagingStructuresPAE.cpp | 24 ++++-- .../x86/paging/pae/X86PagingStructuresPAE.h | 3 +- .../x86/paging/pae/X86VMTranslationMapPAE.cpp | 85 +++++++++++++++++-- 3 files changed, 98 insertions(+), 14 deletions(-) diff --git a/src/system/kernel/arch/x86/paging/pae/X86PagingStructuresPAE.cpp b/src/system/kernel/arch/x86/paging/pae/X86PagingStructuresPAE.cpp index f49a034f60..75dab1fc11 100644 --- a/src/system/kernel/arch/x86/paging/pae/X86PagingStructuresPAE.cpp +++ b/src/system/kernel/arch/x86/paging/pae/X86PagingStructuresPAE.cpp @@ -6,34 +6,46 @@ #include "paging/pae/X86PagingStructuresPAE.h" +#include #include #include +#include + +#include "paging/pae/X86PagingMethodPAE.h" + #if B_HAIKU_PHYSICAL_BITS == 64 X86PagingStructuresPAE::X86PagingStructuresPAE() { + fVirtualPageDirs[0] = NULL; } X86PagingStructuresPAE::~X86PagingStructuresPAE() { -// TODO: Implement! - panic("X86PagingStructuresPAE::~X86PagingStructuresPAE(): not implemented"); + // free the user page dirs + free(fVirtualPageDirs[0]); + + // free the PDPT page + X86PagingMethodPAE::Method()->Free32BitPage(fPageDirPointerTable, + pgdir_phys, fPageDirPointerTableHandle); } void X86PagingStructuresPAE::Init( pae_page_directory_pointer_table_entry* virtualPDPT, - phys_addr_t physicalPDPT, pae_page_directory_entry* const* virtualPageDirs, + phys_addr_t physicalPDPT, void* pdptHandle, + pae_page_directory_entry* const* virtualPageDirs, const phys_addr_t* physicalPageDirs) { fPageDirPointerTable = virtualPDPT; pgdir_phys = physicalPDPT; + fPageDirPointerTableHandle = pdptHandle; memcpy(fVirtualPageDirs, virtualPageDirs, sizeof(fVirtualPageDirs)); memcpy(fPhysicalPageDirs, physicalPageDirs, sizeof(fPhysicalPageDirs)); } @@ -42,8 +54,10 @@ X86PagingStructuresPAE::Init( void X86PagingStructuresPAE::Delete() { -// TODO: Implement! - panic("X86PagingStructuresPAE::Delete(): not implemented"); + if (are_interrupts_enabled()) + delete this; + else + deferred_delete(this); } diff --git a/src/system/kernel/arch/x86/paging/pae/X86PagingStructuresPAE.h b/src/system/kernel/arch/x86/paging/pae/X86PagingStructuresPAE.h index 524e91f37d..8c91e7438c 100644 --- a/src/system/kernel/arch/x86/paging/pae/X86PagingStructuresPAE.h +++ b/src/system/kernel/arch/x86/paging/pae/X86PagingStructuresPAE.h @@ -19,7 +19,7 @@ struct X86PagingStructuresPAE : X86PagingStructures { void Init(pae_page_directory_pointer_table_entry* virtualPDPT, - phys_addr_t physicalPDPT, + phys_addr_t physicalPDPT, void* pdptHandle, pae_page_directory_entry* const* virtualPageDirs, const phys_addr_t* physicalPageDirs); @@ -31,6 +31,7 @@ struct X86PagingStructuresPAE : X86PagingStructures { private: pae_page_directory_pointer_table_entry* fPageDirPointerTable; + void* fPageDirPointerTableHandle; pae_page_directory_entry* fVirtualPageDirs[4]; phys_addr_t fPhysicalPageDirs[4]; }; diff --git a/src/system/kernel/arch/x86/paging/pae/X86VMTranslationMapPAE.cpp b/src/system/kernel/arch/x86/paging/pae/X86VMTranslationMapPAE.cpp index df89d6d0fe..97a7bd85aa 100644 --- a/src/system/kernel/arch/x86/paging/pae/X86VMTranslationMapPAE.cpp +++ b/src/system/kernel/arch/x86/paging/pae/X86VMTranslationMapPAE.cpp @@ -43,7 +43,40 @@ X86VMTranslationMapPAE::X86VMTranslationMapPAE() X86VMTranslationMapPAE::~X86VMTranslationMapPAE() { -// TODO: Implement! + if (fPagingStructures == NULL) + return; + + if (fPageMapper != NULL) + fPageMapper->Delete(); + + // cycle through and free all of the user space page tables + + STATIC_ASSERT(KERNEL_BASE == 0x80000000 && KERNEL_SIZE == 0x80000000); + // assuming 1-1 split of the address space + + for (uint32 k = 0; k < 2; k++) { + pae_page_directory_entry* pageDir + = fPagingStructures->VirtualPageDirs()[k]; + if (pageDir == NULL) + continue; + + for (uint32 i = 0; i < kPAEPageDirEntryCount; i++) { + if ((pageDir[i] & X86_PAE_PDE_PRESENT) != 0) { + phys_addr_t address = pageDir[i] & X86_PAE_PDE_ADDRESS_MASK; + vm_page* page = vm_lookup_page(address / B_PAGE_SIZE); + if (page == NULL) + panic("X86VMTranslationMapPAE::~X86VMTranslationMapPAE: " + "didn't find page table page: page address: %#" + B_PRIxPHYSADDR ", virtual base: %#" B_PRIxADDR "\n", + address, + (k * kPAEPageDirEntryCount + i) * kPAEPageTableRange); + DEBUG_PAGE_ACCESS_START(page); + vm_page_set_state(page, PAGE_STATE_FREE); + } + } + } + + fPagingStructures->RemoveReference(); } @@ -67,7 +100,7 @@ X86VMTranslationMapPAE::Init(bool kernel) // we already know the kernel pgdir mapping fPagingStructures->Init(method->KernelVirtualPageDirPointerTable(), - method->KernelPhysicalPageDirPointerTable(), + method->KernelPhysicalPageDirPointerTable(), NULL, method->KernelVirtualPageDirs(), method->KernelPhysicalPageDirs()); } else { // user @@ -124,7 +157,7 @@ X86VMTranslationMapPAE::Init(bool kernel) } // init the paging structures - fPagingStructures->Init(pdpt, physicalPDPT, virtualPageDirs, + fPagingStructures->Init(pdpt, physicalPDPT, pdptHandle, virtualPageDirs, physicalPageDirs); } @@ -455,12 +488,48 @@ X86VMTranslationMapPAE::Query(addr_t virtualAddress, status_t -X86VMTranslationMapPAE::QueryInterrupt(addr_t va, phys_addr_t *_physical, - uint32 *_flags) +X86VMTranslationMapPAE::QueryInterrupt(addr_t virtualAddress, + phys_addr_t* _physicalAddress, uint32* _flags) { -// TODO: Implement! - panic("X86VMTranslationMapPAE::QueryInterrupt(): not implemented"); - return B_UNSUPPORTED; + // default the flags to not present + *_flags = 0; + *_physicalAddress = 0; + + // get the page directory entry + pae_page_directory_entry* pageDirEntry + = X86PagingMethodPAE::PageDirEntryForAddress( + fPagingStructures->VirtualPageDirs(), virtualAddress); + if ((*pageDirEntry & X86_PAE_PDE_PRESENT) == 0) { + // no pagetable here + return B_OK; + } + + // get the page table entry + pae_page_table_entry* pageTable + = (pae_page_table_entry*)X86PagingMethodPAE::Method() + ->PhysicalPageMapper()->InterruptGetPageTableAt( + *pageDirEntry & X86_PAE_PDE_ADDRESS_MASK); + pae_page_table_entry entry + = pageTable[virtualAddress / B_PAGE_SIZE % kPAEPageTableEntryCount]; + + *_physicalAddress = entry & X86_PAE_PTE_ADDRESS_MASK; + + // translate the page state flags + if ((entry & X86_PAE_PTE_USER) != 0) { + *_flags |= ((entry & X86_PAE_PTE_WRITABLE) != 0 ? B_WRITE_AREA : 0) + | B_READ_AREA; + } + + *_flags |= ((entry & X86_PAE_PTE_WRITABLE) != 0 ? B_KERNEL_WRITE_AREA : 0) + | B_KERNEL_READ_AREA + | ((entry & X86_PAE_PTE_DIRTY) != 0 ? PAGE_MODIFIED : 0) + | ((entry & X86_PAE_PTE_ACCESSED) != 0 ? PAGE_ACCESSED : 0) + | ((entry & X86_PAE_PTE_PRESENT) != 0 ? PAGE_PRESENT : 0); + + TRACE("X86VMTranslationMapPAE::Query(%#" B_PRIxADDR ") -> %#" + B_PRIxPHYSADDR ":\n", *_physicalAddress, virtualAddress); + + return B_OK; }