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 phys_addr_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 static void _EarlyPreparePageTables( 81 page_table_entry* pageTables, 82 addr_t address, size_t size); 83 static status_t _EarlyQuery(addr_t virtualAddress, 84 phys_addr_t *_physicalAddress); 85 86 private: 87 uint32 fKernelPhysicalPageDirectory; 88 page_directory_entry* fKernelVirtualPageDirectory; 89 90 ARMPhysicalPageMapper* fPhysicalPageMapper; 91 TranslationMapPhysicalPageMapper* fKernelPhysicalPageMapper; 92 }; 93 94 95 /*static*/ inline ARMPagingMethod32Bit* 96 ARMPagingMethod32Bit::Method() 97 { 98 return static_cast<ARMPagingMethod32Bit*>(gARMPagingMethod); 99 } 100 101 102 /*static*/ inline page_table_entry 103 ARMPagingMethod32Bit::SetPageTableEntry(page_table_entry* entry, 104 page_table_entry newEntry) 105 { 106 return atomic_set((int32*)entry, newEntry); 107 } 108 109 110 /*static*/ inline page_table_entry 111 ARMPagingMethod32Bit::SetPageTableEntryFlags(page_table_entry* entry, 112 uint32 flags) 113 { 114 return atomic_or((int32*)entry, flags); 115 } 116 117 118 /*static*/ inline page_table_entry 119 ARMPagingMethod32Bit::TestAndSetPageTableEntry(page_table_entry* entry, 120 page_table_entry newEntry, page_table_entry oldEntry) 121 { 122 return atomic_test_and_set((int32*)entry, newEntry, oldEntry); 123 } 124 125 126 /*static*/ inline page_table_entry 127 ARMPagingMethod32Bit::ClearPageTableEntry(page_table_entry* entry) 128 { 129 return SetPageTableEntry(entry, 0); 130 } 131 132 133 /*static*/ inline page_table_entry 134 ARMPagingMethod32Bit::ClearPageTableEntryFlags(page_table_entry* entry, uint32 flags) 135 { 136 return atomic_and((int32*)entry, ~flags); 137 } 138 139 140 /*static*/ inline uint32 141 ARMPagingMethod32Bit::MemoryTypeToPageTableEntryFlags(uint32 memoryType) 142 { 143 #if 0 //IRA 144 // ATM we only handle the uncacheable and write-through type explicitly. For 145 // all other types we rely on the MTRRs to be set up correctly. Since we set 146 // the default memory type to write-back and since the uncacheable type in 147 // the PTE overrides any MTRR attribute (though, as per the specs, that is 148 // not recommended for performance reasons), this reduces the work we 149 // actually *have* to do with the MTRRs to setting the remaining types 150 // (usually only write-combining for the frame buffer). 151 switch (memoryType) { 152 case B_MTR_UC: 153 return ARM_PTE_CACHING_DISABLED | ARM_PTE_WRITE_THROUGH; 154 155 case B_MTR_WC: 156 // ARM_PTE_WRITE_THROUGH would be closer, but the combination with 157 // MTRR WC is "implementation defined" for Pentium Pro/II. 158 return 0; 159 160 case B_MTR_WT: 161 return ARM_PTE_WRITE_THROUGH; 162 163 case B_MTR_WP: 164 case B_MTR_WB: 165 default: 166 return 0; 167 } 168 #else 169 return 0; 170 #endif 171 } 172 173 174 #endif // KERNEL_ARCH_ARM_PAGING_32_BIT_ARM_PAGING_METHOD_32_BIT_H 175