/* * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #ifndef KERNEL_ARCH_PPC_PAGING_CLASSIC_PPC_PAGING_METHOD_CLASSIC_H #define KERNEL_ARCH_PPC_PAGING_CLASSIC_PPC_PAGING_METHOD_CLASSIC_H #include //#include "paging/classic/paging.h" #include "paging/PPCPagingMethod.h" #include "paging/PPCPagingStructures.h" #include "GenericVMPhysicalPageMapper.h" class TranslationMapPhysicalPageMapper; class PPCPagingMethodClassic : public PPCPagingMethod { public: PPCPagingMethodClassic(); virtual ~PPCPagingMethodClassic(); virtual status_t Init(kernel_args* args, VMPhysicalPageMapper** _physicalPageMapper); virtual status_t InitPostArea(kernel_args* args); virtual status_t CreateTranslationMap(bool kernel, VMTranslationMap** _map); virtual status_t MapEarly(kernel_args* args, addr_t virtualAddress, phys_addr_t physicalAddress, uint8 attributes, page_num_t (*get_free_page)(kernel_args*)); virtual bool IsKernelPageAccessible(addr_t virtualAddress, uint32 protection); #if 0//X86 inline page_table_entry* PageHole() const { return fPageHole; } inline page_directory_entry* PageHolePageDir() const { return fPageHolePageDir; } inline uint32 KernelPhysicalPageDirectory() const { return fKernelPhysicalPageDirectory; } inline page_directory_entry* KernelVirtualPageDirectory() const { return fKernelVirtualPageDirectory; } inline PPCPhysicalPageMapper* PhysicalPageMapper() const { return fPhysicalPageMapper; } inline TranslationMapPhysicalPageMapper* KernelPhysicalPageMapper() const { return fKernelPhysicalPageMapper; } #endif inline page_table_entry_group* PageTable() const { return fPageTable; } inline size_t PageTableSize() const { return fPageTableSize; } inline uint32 PageTableHashMask() const { return fPageTableHashMask; } static PPCPagingMethodClassic* Method(); void FillPageTableEntry(page_table_entry *entry, uint32 virtualSegmentID, addr_t virtualAddress, phys_addr_t physicalAddress, uint8 protection, uint32 memoryType, bool secondaryHash); #if 0//X86 static void PutPageTableInPageDir( page_directory_entry* entry, phys_addr_t pgtablePhysical, uint32 attributes); static void PutPageTableEntryInTable( page_table_entry* entry, phys_addr_t physicalAddress, uint32 attributes, uint32 memoryType, bool globalPage); static page_table_entry SetPageTableEntry(page_table_entry* entry, page_table_entry newEntry); static page_table_entry SetPageTableEntryFlags(page_table_entry* entry, uint32 flags); static page_table_entry TestAndSetPageTableEntry( page_table_entry* entry, page_table_entry newEntry, page_table_entry oldEntry); static page_table_entry ClearPageTableEntry(page_table_entry* entry); static page_table_entry ClearPageTableEntryFlags( page_table_entry* entry, uint32 flags); static uint32 MemoryTypeToPageTableEntryFlags( uint32 memoryType); #endif private: //XXX:x86 struct PhysicalPageSlotPool; friend struct PhysicalPageSlotPool; private: #if 0//X86 static void _EarlyPreparePageTables( page_table_entry* pageTables, addr_t address, size_t size); static status_t _EarlyQuery(addr_t virtualAddress, phys_addr_t *_physicalAddress); #endif private: struct page_table_entry_group *fPageTable; size_t fPageTableSize; uint32 fPageTableHashMask; area_id fPageTableArea; GenericVMPhysicalPageMapper fPhysicalPageMapper; #if 0 //XXX:x86 page_table_entry* fPageHole; page_directory_entry* fPageHolePageDir; uint32 fKernelPhysicalPageDirectory; page_directory_entry* fKernelVirtualPageDirectory; PPCPhysicalPageMapper* fPhysicalPageMapper; TranslationMapPhysicalPageMapper* fKernelPhysicalPageMapper; #endif }; /*static*/ inline PPCPagingMethodClassic* PPCPagingMethodClassic::Method() { return static_cast(gPPCPagingMethod); } #if 0//X86 /*static*/ inline page_table_entry PPCPagingMethodClassic::SetPageTableEntry(page_table_entry* entry, page_table_entry newEntry) { return atomic_set((int32*)entry, newEntry); } /*static*/ inline page_table_entry PPCPagingMethodClassic::SetPageTableEntryFlags(page_table_entry* entry, uint32 flags) { return atomic_or((int32*)entry, flags); } /*static*/ inline page_table_entry PPCPagingMethodClassic::TestAndSetPageTableEntry(page_table_entry* entry, page_table_entry newEntry, page_table_entry oldEntry) { return atomic_test_and_set((int32*)entry, newEntry, oldEntry); } /*static*/ inline page_table_entry PPCPagingMethodClassic::ClearPageTableEntry(page_table_entry* entry) { return SetPageTableEntry(entry, 0); } /*static*/ inline page_table_entry PPCPagingMethodClassic::ClearPageTableEntryFlags(page_table_entry* entry, uint32 flags) { return atomic_and((int32*)entry, ~flags); } /*static*/ inline uint32 PPCPagingMethodClassic::MemoryTypeToPageTableEntryFlags(uint32 memoryType) { // ATM we only handle the uncacheable and write-through type explicitly. For // all other types we rely on the MTRRs to be set up correctly. Since we set // the default memory type to write-back and since the uncacheable type in // the PTE overrides any MTRR attribute (though, as per the specs, that is // not recommended for performance reasons), this reduces the work we // actually *have* to do with the MTRRs to setting the remaining types // (usually only write-combining for the frame buffer). switch (memoryType) { case B_MTR_UC: return PPC_PTE_CACHING_DISABLED | PPC_PTE_WRITE_THROUGH; case B_MTR_WC: // PPC_PTE_WRITE_THROUGH would be closer, but the combination with // MTRR WC is "implementation defined" for Pentium Pro/II. return 0; case B_MTR_WT: return PPC_PTE_WRITE_THROUGH; case B_MTR_WP: case B_MTR_WB: default: return 0; } } #endif//X86 #endif // KERNEL_ARCH_PPC_PAGING_CLASSIC_PPC_PAGING_METHOD_CLASSIC_H