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 /* Make sure the list isn't empty and loop it */ 154 ASSERT(Pfn1 != (PVOID)LIST_HEAD); 155 while (Pfn1 != (PVOID)LIST_HEAD) 156 { 157 /* Get the page index for this PFN */ 158 PageFrameIndex = MiGetPfnEntryIndex(Pfn1); 159 160 // 161 // Write the PFN 162 // 163 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 164 165 // 166 // Set the correct PTE to write to, and set its new value 167 // 168 PointerPte--; 169 MI_WRITE_VALID_PTE(PointerPte, TempPte); 170 171 /* Move to the next PFN */ 172 Pfn1 = (PMMPFN)Pfn1->u1.Flink; 173 } 174 175 // 176 // Return the address 177 // 178 return MiPteToAddress(PointerPte); 179 } 180 181 VOID 182 NTAPI 183 MiUnmapPagesInZeroSpace(IN PVOID VirtualAddress, 184 IN PFN_NUMBER NumberOfPages) 185 { 186 PMMPTE PointerPte; 187 188 // 189 // Sanity checks 190 // 191 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); 192 ASSERT (NumberOfPages != 0); 193 ASSERT(NumberOfPages <= MI_ZERO_PTES); 194 195 // 196 // Get the first PTE for the mapped zero VA 197 // 198 PointerPte = MiAddressToPte(VirtualAddress); 199 200 // 201 // Blow away the mapped zero PTEs 202 // 203 RtlZeroMemory(PointerPte, NumberOfPages * sizeof(MMPTE)); 204 } 205 206