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