1 /* 2 * Copyright 2010, Ithamar R. Adema, ithamar.adema@team-embedded.nl 3 * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef KERNEL_ARCH_ARM_PAGING_32_BIT_ARM_PAGING_METHOD_32_BIT_H 7 #define KERNEL_ARCH_ARM_PAGING_32_BIT_ARM_PAGING_METHOD_32_BIT_H 8 9 10 #include "paging/32bit/paging.h" 11 #include "paging/ARMPagingMethod.h" 12 #include "paging/ARMPagingStructures.h" 13 14 15 class TranslationMapPhysicalPageMapper; 16 class ARMPhysicalPageMapper; 17 18 19 class ARMPagingMethod32Bit : public ARMPagingMethod { 20 public: 21 ARMPagingMethod32Bit(); 22 virtual ~ARMPagingMethod32Bit(); 23 24 virtual status_t Init(kernel_args* args, 25 VMPhysicalPageMapper** _physicalPageMapper); 26 virtual status_t InitPostArea(kernel_args* args); 27 28 virtual status_t CreateTranslationMap(bool kernel, 29 VMTranslationMap** _map); 30 31 virtual status_t MapEarly(kernel_args* args, 32 addr_t virtualAddress, 33 phys_addr_t physicalAddress, 34 uint8 attributes, 35 page_num_t (*get_free_page)(kernel_args*)); 36 37 virtual bool IsKernelPageAccessible(addr_t virtualAddress, 38 uint32 protection); 39 40 inline uint32 KernelPhysicalPageDirectory() const 41 { return fKernelPhysicalPageDirectory; } 42 inline page_directory_entry* KernelVirtualPageDirectory() const 43 { return fKernelVirtualPageDirectory; } 44 inline ARMPhysicalPageMapper* PhysicalPageMapper() const 45 { return fPhysicalPageMapper; } 46 inline TranslationMapPhysicalPageMapper* KernelPhysicalPageMapper() const 47 { return fKernelPhysicalPageMapper; } 48 49 static ARMPagingMethod32Bit* Method(); 50 51 static void PutPageTableInPageDir( 52 page_directory_entry* entry, 53 phys_addr_t pgtablePhysical, 54 uint32 attributes); 55 static void PutPageTableEntryInTable( 56 page_table_entry* entry, 57 phys_addr_t physicalAddress, 58 uint32 attributes, uint32 memoryType, 59 bool globalPage); 60 static page_table_entry SetPageTableEntry(page_table_entry* entry, 61 page_table_entry newEntry); 62 static page_table_entry SetPageTableEntryFlags(page_table_entry* entry, 63 uint32 flags); 64 static page_table_entry TestAndSetPageTableEntry( 65 page_table_entry* entry, 66 page_table_entry newEntry, 67 page_table_entry oldEntry); 68 static page_table_entry ClearPageTableEntry(page_table_entry* entry); 69 static page_table_entry ClearPageTableEntryFlags( 70 page_table_entry* entry, uint32 flags); 71 72 static uint32 MemoryTypeToPageTableEntryFlags( 73 uint32 memoryType); 74 75 private: 76 struct PhysicalPageSlotPool; 77 friend struct PhysicalPageSlotPool; 78 79 private: 80 inline int32 _GetInitialPoolCount(); 81 82 static void _EarlyPreparePageTables( 83 page_table_entry* pageTables, 84 addr_t address, size_t size); 85 static status_t _EarlyQuery(addr_t virtualAddress, 86 phys_addr_t *_physicalAddress); 87 88 private: 89 uint32 fKernelPhysicalPageDirectory; 90 page_directory_entry* fKernelVirtualPageDirectory; 91 92 ARMPhysicalPageMapper* fPhysicalPageMapper; 93 TranslationMapPhysicalPageMapper* fKernelPhysicalPageMapper; 94 }; 95 96 97 /*static*/ inline ARMPagingMethod32Bit* 98 ARMPagingMethod32Bit::Method() 99 { 100 return static_cast<ARMPagingMethod32Bit*>(gARMPagingMethod); 101 } 102 103 104 /*static*/ inline page_table_entry 105 ARMPagingMethod32Bit::SetPageTableEntry(page_table_entry* entry, 106 page_table_entry newEntry) 107 { 108 return atomic_get_and_set((int32*)entry, newEntry); 109 } 110 111 112 /*static*/ inline page_table_entry 113 ARMPagingMethod32Bit::SetPageTableEntryFlags(page_table_entry* entry, 114 uint32 flags) 115 { 116 return atomic_or((int32*)entry, flags); 117 } 118 119 120 /*static*/ inline page_table_entry 121 ARMPagingMethod32Bit::TestAndSetPageTableEntry(page_table_entry* entry, 122 page_table_entry newEntry, page_table_entry oldEntry) 123 { 124 return atomic_test_and_set((int32*)entry, newEntry, oldEntry); 125 } 126 127 128 /*static*/ inline page_table_entry 129 ARMPagingMethod32Bit::ClearPageTableEntry(page_table_entry* entry) 130 { 131 return SetPageTableEntry(entry, 0); 132 } 133 134 135 /*static*/ inline page_table_entry 136 ARMPagingMethod32Bit::ClearPageTableEntryFlags(page_table_entry* entry, uint32 flags) 137 { 138 return atomic_and((int32*)entry, ~flags); 139 } 140 141 142 /*static*/ inline uint32 143 ARMPagingMethod32Bit::MemoryTypeToPageTableEntryFlags(uint32 memoryType) 144 { 145 #if 0 //IRA 146 // ATM we only handle the uncacheable and write-through type explicitly. For 147 // all other types we rely on the MTRRs to be set up correctly. Since we set 148 // the default memory type to write-back and since the uncacheable type in 149 // the PTE overrides any MTRR attribute (though, as per the specs, that is 150 // not recommended for performance reasons), this reduces the work we 151 // actually *have* to do with the MTRRs to setting the remaining types 152 // (usually only write-combining for the frame buffer). 153 switch (memoryType) { 154 case B_MTR_UC: 155 return X86_PTE_CACHING_DISABLED | X86_PTE_WRITE_THROUGH; 156 157 case B_MTR_WC: 158 // ARM_PTE_WRITE_THROUGH would be closer, but the combination with 159 // MTRR WC is "implementation defined" for Pentium Pro/II. 160 return 0; 161 162 case B_MTR_WT: 163 return X86_PTE_WRITE_THROUGH; 164 165 case B_MTR_WP: 166 case B_MTR_WB: 167 default: 168 return 0; 169 } 170 #else 171 return 0; 172 #endif 173 } 174 175 176 #endif // KERNEL_ARCH_ARM_PAGING_32_BIT_ARM_PAGING_METHOD_32_BIT_H 177