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