1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: ntoskrnl/mm/ARM3/hypermap.c 5 * PURPOSE: ARM Memory Manager Hyperspace Mapping Functionality 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 #define MODULE_INVOLVED_IN_ARM3 16 #include <mm/ARM3/miarm.h> 17 18 /* GLOBALS ********************************************************************/ 19 20 PMMPTE MmFirstReservedMappingPte, MmLastReservedMappingPte; 21 PMMPTE MiFirstReservedZeroingPte; 22 MMPTE HyperTemplatePte; 23 24 /* PRIVATE FUNCTIONS **********************************************************/ 25 26 PVOID 27 NTAPI 28 MiMapPageInHyperSpace(IN PEPROCESS Process, 29 IN PFN_NUMBER Page, 30 IN PKIRQL OldIrql) 31 { 32 MMPTE TempPte; 33 PMMPTE PointerPte; 34 PFN_NUMBER Offset; 35 36 // 37 // Never accept page 0 or non-physical pages 38 // 39 ASSERT(Page != 0); 40 ASSERT(MiGetPfnEntry(Page) != NULL); 41 42 // 43 // Build the PTE 44 // 45 TempPte = ValidKernelPteLocal; 46 TempPte.u.Hard.PageFrameNumber = Page; 47 48 // 49 // Pick the first hyperspace PTE 50 // 51 PointerPte = MmFirstReservedMappingPte; 52 53 // 54 // Acquire the hyperlock 55 // 56 ASSERT(Process == PsGetCurrentProcess()); 57 KeAcquireSpinLock(&Process->HyperSpaceLock, OldIrql); 58 59 // 60 // Now get the first free PTE 61 // 62 Offset = PFN_FROM_PTE(PointerPte); 63 if (!Offset) 64 { 65 // 66 // Reset the PTEs 67 // 68 Offset = MI_HYPERSPACE_PTES; 69 KeFlushProcessTb(); 70 } 71 72 // 73 // Prepare the next PTE 74 // 75 PointerPte->u.Hard.PageFrameNumber = Offset - 1; 76 77 // 78 // Write the current PTE 79 // 80 PointerPte += Offset; 81 MI_WRITE_VALID_PTE(PointerPte, TempPte); 82 83 // 84 // Return the address 85 // 86 return MiPteToAddress(PointerPte); 87 } 88 89 VOID 90 NTAPI 91 MiUnmapPageInHyperSpace(IN PEPROCESS Process, 92 IN PVOID Address, 93 IN KIRQL OldIrql) 94 { 95 ASSERT(Process == PsGetCurrentProcess()); 96 97 // 98 // Blow away the mapping 99 // 100 MiAddressToPte(Address)->u.Long = 0; 101 102 // 103 // Release the hyperlock 104 // 105 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 106 KeReleaseSpinLock(&Process->HyperSpaceLock, OldIrql); 107 } 108 109 PVOID 110 NTAPI 111 MiMapPagesInZeroSpace(IN PMMPFN Pfn1, 112 IN PFN_NUMBER NumberOfPages) 113 { 114 MMPTE TempPte; 115 PMMPTE PointerPte; 116 PFN_NUMBER Offset, PageFrameIndex; 117 118 // 119 // Sanity checks 120 // 121 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); 122 ASSERT(NumberOfPages != 0); 123 ASSERT(NumberOfPages <= MI_ZERO_PTES); 124 125 // 126 // Pick the first zeroing PTE 127 // 128 PointerPte = MiFirstReservedZeroingPte; 129 130 // 131 // Now get the first free PTE 132 // 133 Offset = PFN_FROM_PTE(PointerPte); 134 if (NumberOfPages > Offset) 135 { 136 // 137 // Reset the PTEs 138 // 139 Offset = MI_ZERO_PTES; 140 PointerPte->u.Hard.PageFrameNumber = Offset; 141 KeFlushProcessTb(); 142 } 143 144 // 145 // Prepare the next PTE 146 // 147 PointerPte->u.Hard.PageFrameNumber = Offset - NumberOfPages; 148 149 /* Choose the correct PTE to use, and which template */ 150 PointerPte += (Offset + 1); 151 TempPte = ValidKernelPte; 152 153 /* Disable cache. Write through */ 154 MI_PAGE_DISABLE_CACHE(&TempPte); 155 MI_PAGE_WRITE_THROUGH(&TempPte); 156 157 /* Make sure the list isn't empty and loop it */ 158 ASSERT(Pfn1 != (PVOID)LIST_HEAD); 159 while (Pfn1 != (PVOID)LIST_HEAD) 160 { 161 /* Get the page index for this PFN */ 162 PageFrameIndex = MiGetPfnEntryIndex(Pfn1); 163 164 // 165 // Write the PFN 166 // 167 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 168 169 // 170 // Set the correct PTE to write to, and set its new value 171 // 172 PointerPte--; 173 MI_WRITE_VALID_PTE(PointerPte, TempPte); 174 175 /* Move to the next PFN */ 176 Pfn1 = (PMMPFN)Pfn1->u1.Flink; 177 } 178 179 // 180 // Return the address 181 // 182 return MiPteToAddress(PointerPte); 183 } 184 185 VOID 186 NTAPI 187 MiUnmapPagesInZeroSpace(IN PVOID VirtualAddress, 188 IN PFN_NUMBER NumberOfPages) 189 { 190 PMMPTE PointerPte; 191 192 // 193 // Sanity checks 194 // 195 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); 196 ASSERT (NumberOfPages != 0); 197 ASSERT(NumberOfPages <= MI_ZERO_PTES); 198 199 // 200 // Get the first PTE for the mapped zero VA 201 // 202 PointerPte = MiAddressToPte(VirtualAddress); 203 204 // 205 // Blow away the mapped zero PTEs 206 // 207 RtlZeroMemory(PointerPte, NumberOfPages * sizeof(MMPTE)); 208 } 209 210