Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

hypermap.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 Copyright (c) 1993 IBM Corporation 00005 00006 Module Name: 00007 00008 hypermap.c 00009 00010 Abstract: 00011 00012 This module contains the routines which map physical pages into 00013 reserved PTEs within hyper space. 00014 00015 This module is machine dependent. This version is targetted 00016 for PowerPC. 00017 00018 Author: 00019 00020 Lou Perazzoli (loup) 5-Apr-1989 00021 00022 Modified for PowerPC by Mark Mergen ([email protected]) 11-Oct-1993 00023 00024 Revision History: 00025 00026 --*/ 00027 00028 #include "mi.h" 00029 00030 00031 PVOID 00032 MiMapPageInHyperSpace ( 00033 IN ULONG PageFrameIndex, 00034 IN PKIRQL OldIrql 00035 ) 00036 00037 /*++ 00038 00039 Routine Description: 00040 00041 This routine maps the specified physical page into hyperspace 00042 and returns the virtual address that maps the page. 00043 00044 ************************************ 00045 * * 00046 * Returns with a spin lock held!!! * 00047 * * 00048 ************************************ 00049 00050 Arguments: 00051 00052 PageFrameIndex - Supplies the physical page number to map. 00053 00054 Return Value: 00055 00056 Virtual address in hyperspace that maps the page. 00057 00058 RETURNS WITH THE HYPERSPACE SPIN LOCK HELD!!!! 00059 00060 The routine MiUnmapPageInHyperSpace MUST be called to release the lock!!!! 00061 00062 Environment: 00063 00064 Kernel mode. 00065 00066 --*/ 00067 00068 { 00069 ULONG i; 00070 PMMPTE PointerPte; 00071 MMPTE TempPte; 00072 00073 #if DBG 00074 if (PageFrameIndex == 0) { 00075 DbgPrint("attempt to map physical page 0 in hyper space\n"); 00076 KeBugCheck (MEMORY_MANAGEMENT); 00077 } 00078 #endif //DBG 00079 00080 // 00081 // Find the proper location in hyper space and map the page there. 00082 // 00083 00084 LOCK_HYPERSPACE(OldIrql); 00085 PointerPte = MmFirstReservedMappingPte; 00086 if (PointerPte->u.Hard.Valid == 1) { 00087 00088 // 00089 // All the pages in reserved for mapping have been used, 00090 // flush the TB and reinitialize the pages. 00091 // 00092 00093 RtlZeroMemory ((PVOID)MmFirstReservedMappingPte, 00094 (NUMBER_OF_MAPPING_PTES + 1) * sizeof(MMPTE)); 00095 PointerPte->u.Hard.PageFrameNumber = NUMBER_OF_MAPPING_PTES; 00096 KeFlushEntireTb (TRUE, FALSE); 00097 00098 } 00099 00100 // 00101 // Get the offset to the first free PTE. 00102 // 00103 00104 i = PointerPte->u.Hard.PageFrameNumber; 00105 00106 // 00107 // Change the offset for the next time through. 00108 // 00109 00110 PointerPte->u.Hard.PageFrameNumber = i - 1; 00111 00112 // 00113 // Point to the free entry and make it valid. 00114 // 00115 00116 PointerPte += i; 00117 00118 ASSERT (PointerPte->u.Hard.Valid == 0); 00119 00120 TempPte = ValidPtePte; 00121 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 00122 *PointerPte = TempPte; 00123 00124 return MiGetVirtualAddressMappedByPte (PointerPte); 00125 } 00126 00127 PVOID 00128 MiMapImageHeaderInHyperSpace ( 00129 IN ULONG PageFrameIndex 00130 ) 00131 00132 /*++ 00133 00134 Routine Description: 00135 00136 This routine maps the specified physical page into hyperspace 00137 at the address reserved explicitly for image page header mapping 00138 and returns the virtual address that maps the page. No other 00139 hyperspace maps will affect this map. If another thread attempts 00140 to map an image at the same time, it will be forced to wait until 00141 this header is unmapped. 00142 00143 Arguments: 00144 00145 PageFrameIndex - Supplies the physical page number to map. 00146 00147 Return Value: 00148 00149 Virtual address in hyperspace that maps the page. 00150 00151 Environment: 00152 00153 Kernel mode. 00154 00155 --*/ 00156 00157 { 00158 MMPTE TempPte; 00159 PMMPTE PointerPte; 00160 KIRQL OldIrql; 00161 00162 #if DBG 00163 if (PageFrameIndex == 0) { 00164 DbgPrint("attempt to map physical page 0 in hyper space\n"); 00165 KeBugCheck (MEMORY_MANAGEMENT); 00166 } 00167 #endif //DBG 00168 00169 PointerPte = MiGetPteAddress (IMAGE_MAPPING_PTE); 00170 00171 LOCK_PFN (OldIrql); 00172 00173 while (PointerPte->u.Long != 0) { 00174 00175 // 00176 // If there is no event specified, set one up. 00177 // 00178 00179 if (MmWorkingSetList->WaitingForImageMapping == (PKEVENT)NULL) { 00180 00181 // 00182 // Set the global event into the field and wait for it. 00183 // 00184 00185 MmWorkingSetList->WaitingForImageMapping = &MmImageMappingPteEvent; 00186 } 00187 00188 // 00189 // Release the PFN lock and wait on the event in an 00190 // atomic operation. 00191 // 00192 00193 KeEnterCriticalRegion(); 00194 UNLOCK_PFN_AND_THEN_WAIT(OldIrql); 00195 00196 KeWaitForSingleObject(MmWorkingSetList->WaitingForImageMapping, 00197 Executive, 00198 KernelMode, 00199 FALSE, 00200 (PLARGE_INTEGER)NULL); 00201 KeLeaveCriticalRegion(); 00202 00203 LOCK_PFN (OldIrql); 00204 } 00205 00206 ASSERT (PointerPte->u.Long == 0); 00207 00208 TempPte = ValidPtePte; 00209 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 00210 00211 *PointerPte = TempPte; 00212 00213 UNLOCK_PFN (OldIrql); 00214 00215 return (PVOID)MiGetVirtualAddressMappedByPte (PointerPte); 00216 } 00217 00218 VOID 00219 MiUnmapImageHeaderInHyperSpace ( 00220 VOID 00221 ) 00222 00223 /*++ 00224 00225 Routine Description: 00226 00227 This procedure unmaps the PTE reserved for mapping the image 00228 header, flushes the TB, and, if the WaitingForImageMapping field 00229 is not NULL, sets the specified event. 00230 00231 Arguments: 00232 00233 None. 00234 00235 Return Value: 00236 00237 None. 00238 00239 Environment: 00240 00241 Kernel mode. 00242 00243 --*/ 00244 00245 { 00246 MMPTE TempPte; 00247 PMMPTE PointerPte; 00248 KIRQL OldIrql; 00249 PKEVENT Event; 00250 00251 PointerPte = MiGetPteAddress (IMAGE_MAPPING_PTE); 00252 00253 TempPte.u.Long = 0; 00254 00255 LOCK_PFN (OldIrql); 00256 00257 // 00258 // Capture the current state of the event field and clear it out. 00259 // 00260 00261 Event = MmWorkingSetList->WaitingForImageMapping; 00262 00263 MmWorkingSetList->WaitingForImageMapping = (PKEVENT)NULL; 00264 00265 ASSERT (PointerPte->u.Long != 0); 00266 00267 KeFlushSingleTb (IMAGE_MAPPING_PTE, 00268 TRUE, 00269 FALSE, 00270 (PHARDWARE_PTE)PointerPte, 00271 TempPte.u.Hard); 00272 00273 UNLOCK_PFN (OldIrql); 00274 00275 if (Event != (PKEVENT)NULL) { 00276 00277 // 00278 // If there was an event specified, set the event. 00279 // 00280 00281 KePulseEvent (Event, 0, FALSE); 00282 } 00283 00284 return; 00285 } 00286 00287 PVOID 00288 MiMapPageToZeroInHyperSpace ( 00289 IN ULONG PageFrameIndex 00290 ) 00291 00292 /*++ 00293 00294 Routine Description: 00295 00296 This procedure maps the specified physical page into hyper space 00297 and returns the virtual address which maps the page. 00298 00299 NOTE: it maps it into the same location reserved for fork operations!! 00300 This is only to be used by the zeroing page thread. 00301 00302 Arguments: 00303 00304 PageFrameIndex - Supplies the physical page number to map. 00305 00306 Return Value: 00307 00308 Returns the virtual address where the specified physical page was 00309 mapped. 00310 00311 Environment: 00312 00313 Must be holding the PFN lock. 00314 00315 --*/ 00316 00317 { 00318 MMPTE TempPte; 00319 PMMPTE PointerPte; 00320 00321 #if DBG 00322 if (PageFrameIndex == 0) { 00323 DbgPrint("attempt to map physical page 0 in hyper space\n"); 00324 KeBugCheck (MEMORY_MANAGEMENT); 00325 } 00326 #endif //DBG 00327 00328 PointerPte = MiGetPteAddress (ZEROING_PAGE_PTE); 00329 00330 TempPte.u.Long = 0; 00331 00332 KeFlushSingleTb (ZEROING_PAGE_PTE, 00333 TRUE, 00334 FALSE, 00335 (PHARDWARE_PTE)PointerPte, 00336 TempPte.u.Hard); 00337 00338 TempPte = ValidPtePte; 00339 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 00340 00341 *PointerPte = TempPte; 00342 00343 return ZEROING_PAGE_PTE; 00344 }

Generated on Sat May 15 19:40:18 2004 for test by doxygen 1.3.7