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

largepag.c File Reference

#include "ki.h"
#include "ki386.h"

Go to the source code of this file.

Defines

#define PTES_PER_PAGE   (PAGE_SIZE / sizeof(HARDWARE_PTE))

Functions

PVOID Ki386AllocateContiguousMemory (IN OUT PIDENTITY_MAP IdentityMap, IN ULONG Pages, IN BOOLEAN Low4Meg)
BOOLEAN Ki386IdentityMapMakeValid (IN OUT PIDENTITY_MAP IdentityMap, IN PHARDWARE_PTE PageTableEntry, OUT PVOID *Page OPTIONAL)
BOOLEAN Ki386MapAddress (IN OUT PIDENTITY_MAP IdentityMap, IN ULONG Va, IN PHYSICAL_ADDRESS PhysicalAddress)
PVOID Ki386ConvertPte (IN OUT PHARDWARE_PTE Pte)
PHYSICAL_ADDRESS Ki386BuildIdentityBuffer (IN OUT PIDENTITY_MAP IdentityMap, IN PVOID StartVa, IN ULONG Length, OUT PULONG PagesToMap)
BOOLEAN Ki386CreateIdentityMap (IN OUT PIDENTITY_MAP IdentityMap, IN PVOID StartVa, IN PVOID EndVa)
VOID Ki386ClearIdentityMap (IN PIDENTITY_MAP IdentityMap)
VOID Ki386EnableTargetLargePage (IN PIDENTITY_MAP IdentityMap)


Define Documentation

#define PTES_PER_PAGE   (PAGE_SIZE / sizeof(HARDWARE_PTE))
 

Definition at line 51 of file largepag.c.

Referenced by Ki386CreateIdentityMap().


Function Documentation

PVOID Ki386AllocateContiguousMemory IN OUT PIDENTITY_MAP  IdentityMap,
IN ULONG  Pages,
IN BOOLEAN  Low4Meg
 

Definition at line 227 of file largepag.c.

References FALSE, MmAllocateContiguousMemory(), NULL, and PAGE_SIZE.

Referenced by Ki386BuildIdentityBuffer(), Ki386IdentityMapMakeValid(), and Ki386MapAddress().

00238 : 00239 00240 IdentityMap - Context pointer for this identity mapping. 00241 00242 Pages - Number of pages to allocate 00243 00244 Low4Meg - Indicates whether the allocation must be below 4M. 00245 00246 Return Value: 00247 00248 Pointer to the new page on success, NULL otherwise. 00249 00250 --*/ 00251 { 00252 ULONG pageListIndex; 00253 PVOID page; 00254 ULONG allocationSize; 00255 PHYSICAL_ADDRESS highestAddress; 00256 00257 if (Low4Meg != FALSE) { 00258 00259 // 00260 // The caller has specified that a page must reside physically 00261 // below 4 MB. 00262 // 00263 00264 highestAddress.LowPart = 0xFFFFFFFF; 00265 highestAddress.HighPart = 0; 00266 00267 } else { 00268 00269 // 00270 // Memory can reside anywhere 00271 // 00272 00273 highestAddress.LowPart = 0xFFFFFFFF; 00274 highestAddress.HighPart = 0xFFFFFFFF; 00275 } 00276 00277 allocationSize = Pages * PAGE_SIZE; 00278 page = MmAllocateContiguousMemory( allocationSize, highestAddress ); 00279 if (page != NULL) { 00280 00281 // 00282 // Record that this page was allocated so that it can be freed when 00283 // the IdentityMap structure is cleared. 00284 // 00285 00286 pageListIndex = IdentityMap->PagesAllocated; 00287 IdentityMap->PageList[ pageListIndex ] = page; 00288 IdentityMap->PagesAllocated++; 00289 00290 // 00291 // Initialize it. 00292 // 00293 00294 RtlZeroMemory( page, allocationSize ); 00295 } 00296 00297 return page; 00298 }

PHYSICAL_ADDRESS Ki386BuildIdentityBuffer IN OUT PIDENTITY_MAP  IdentityMap,
IN PVOID  StartVa,
IN ULONG  Length,
OUT PULONG  PagesToMap
 

Definition at line 515 of file largepag.c.

References ADDRESS_AND_SIZE_TO_SPAN_PAGES, Ki386AllocateContiguousMemory(), MmGetPhysicalAddress(), PAGE_SIZE, and TRUE.

Referenced by Ki386CreateIdentityMap().

00521 { 00522 00523 /*++ 00524 00525 This function checks to see if the physical memory backing a virtual 00526 buffer is physically contiguous and lies completely below 4G. 00527 00528 If these requirements are met, then the physical address of StartVa is 00529 returned. 00530 00531 If not, then a physically contiguous buffer is allocated, the contents 00532 of the region is copied in, and its address is returned. 00533 00534 Arguments: 00535 00536 IdentityMap - Pointer to the identity map building structure. 00537 00538 StartVa - Virtual address of the start of the region for which a 00539 physically contiguous copy is desired. 00540 00541 Length - Length of the region for which a physically contiguous copy 00542 is desired. 00543 00544 --*/ 00545 00546 ULONG pagesToMap; 00547 ULONG pagesRemaining; 00548 PCHAR nextVirtualAddress; 00549 PHYSICAL_ADDRESS nextPhysicalAddress; 00550 PHYSICAL_ADDRESS physicalAddress; 00551 PHYSICAL_ADDRESS firstPhysicalAddress; 00552 ULONG pageOffset; 00553 PCHAR identityBuffer; 00554 00555 // 00556 // Count the number of pages in the buffer, and record the physical 00557 // address of the start of the buffer. 00558 // 00559 00560 pagesToMap = ADDRESS_AND_SIZE_TO_SPAN_PAGES( StartVa, Length ); 00561 nextVirtualAddress = StartVa; 00562 firstPhysicalAddress = MmGetPhysicalAddress( StartVa ); 00563 nextPhysicalAddress = firstPhysicalAddress; 00564 00565 // 00566 // Examine each page in the region. 00567 // 00568 00569 pagesRemaining = pagesToMap; 00570 while (TRUE) { 00571 00572 physicalAddress = MmGetPhysicalAddress( nextVirtualAddress ); 00573 if (physicalAddress.QuadPart != nextPhysicalAddress.QuadPart) { 00574 00575 // 00576 // The buffer is not physically contiguous. 00577 // 00578 00579 break; 00580 } 00581 00582 if (physicalAddress.HighPart != 0) { 00583 00584 // 00585 // The buffer does not lie entirely below 4G 00586 // 00587 00588 break; 00589 } 00590 00591 pagesRemaining -= 1; 00592 if (pagesRemaining == 0) { 00593 00594 // 00595 // All of the pages in the buffer have been examined, and have 00596 // been found to meet the critera. Return the physical address 00597 // of the start of the buffer. 00598 // 00599 00600 *PagesToMap = pagesToMap; 00601 return firstPhysicalAddress; 00602 } 00603 00604 nextVirtualAddress += PAGE_SIZE; 00605 nextPhysicalAddress.QuadPart += PAGE_SIZE; 00606 } 00607 00608 // 00609 // The buffer does not meet the criteria and so its contents must be 00610 // copied to a buffer that does. 00611 // 00612 00613 identityBuffer = Ki386AllocateContiguousMemory( IdentityMap, 00614 pagesToMap, 00615 TRUE ); 00616 if (identityBuffer == 0) { 00617 00618 // 00619 // A contiguous region of the appropriate size could not be located 00620 // below 4G physical. 00621 // 00622 00623 physicalAddress.QuadPart = 0; 00624 00625 } else { 00626 00627 // 00628 // Got an appropriate physical buffer, now copy in the data 00629 // 00630 00631 pageOffset = (ULONG)StartVa & (PAGE_SIZE-1); 00632 identityBuffer += pageOffset; 00633 00634 RtlCopyMemory( identityBuffer, StartVa, Length ); 00635 physicalAddress = MmGetPhysicalAddress( identityBuffer ); 00636 00637 *PagesToMap = pagesToMap; 00638 } 00639 00640 return physicalAddress; 00641 }

VOID Ki386ClearIdentityMap IN PIDENTITY_MAP  IdentityMap  ) 
 

Definition at line 646 of file largepag.c.

References MmFreeContiguousMemory().

Referenced by KiInitMachineDependent().

00649 { 00650 /*++ 00651 00652 This function just frees the page directory and page tables created in 00653 Ki386CreateIdentityMap(). 00654 00655 --*/ 00656 00657 ULONG index; 00658 PVOID page; 00659 00660 // 00661 // IdentityMap->PageList is an array of addresses of pages allocated with 00662 // MmAllocateContiguousMemory(). Walk the array, freeing each page. 00663 // 00664 00665 for (index = 0; index < IdentityMap->PagesAllocated; index++) { 00666 00667 page = IdentityMap->PageList[ index ]; 00668 MmFreeContiguousMemory( page ); 00669 } 00670 }

PVOID Ki386ConvertPte IN OUT PHARDWARE_PTE  Pte  ) 
 

Definition at line 482 of file largepag.c.

References MmGetPhysicalAddress(), and PAGE_SHIFT.

Referenced by Ki386CreateIdentityMap().

00489 : 00490 00491 Pte - Pointer to the page table entry to convert. 00492 00493 Return Value: 00494 00495 None. 00496 00497 --*/ 00498 { 00499 PVOID va; 00500 PHYSICAL_ADDRESS physicalAddress; 00501 00502 va = (PVOID)(Pte->PageFrameNumber << PAGE_SHIFT); 00503 physicalAddress = MmGetPhysicalAddress( va ); 00504 00505 #if defined(_X86PAE_) 00506 Pte->PageFrameNumber = physicalAddress.QuadPart >> PAGE_SHIFT; 00507 #else 00508 Pte->PageFrameNumber = physicalAddress.LowPart >> PAGE_SHIFT; 00509 #endif 00510 00511 return va; 00512 }

BOOLEAN Ki386CreateIdentityMap IN OUT PIDENTITY_MAP  IdentityMap,
IN PVOID  StartVa,
IN PVOID  EndVa
 

Definition at line 54 of file largepag.c.

References FALSE, Ki386BuildIdentityBuffer(), Ki386ConvertPte(), Ki386MapAddress(), MmGetPhysicalAddress(), PAGE_SIZE, PPI_BITS, PTES_PER_PAGE, and TRUE.

Referenced by KiInitMachineDependent().

00059 { 00060 /*++ 00061 00062 This function creates an identity mapping for a region of memory. 00063 00064 If the region of memory passed in includes memory that lies above 00065 4G, then a new buffer is allocated below 4G. 00066 00067 Arguments: 00068 00069 IdentityMap - Pointer to the structure which will be filled with the newly 00070 created top-level directory address. It also provides 00071 storage for the pointers used in alloating and freeing the 00072 memory. 00073 00074 StartVa - Pointer to the first byte of the region of memory that is to be 00075 memory mapped. 00076 00077 EndVa - Pointer to the byte immediately after the last byte of the region 00078 that is to be memory mapped. 00079 00080 Return Value: 00081 00082 TRUE if the function succeeds, FALSE otherwise. 00083 00084 Note - Ki386ClearIdentityMap() should be called even on FALSE return to 00085 free any memory allocated. 00086 00087 --*/ 00088 00089 ULONG pageDirectoryIndex; 00090 ULONG pagesToMap; 00091 PCHAR currentVa; 00092 ULONG length; 00093 BOOLEAN result; 00094 PHARDWARE_PTE pageDirectory; 00095 PHARDWARE_PTE pageDirectoryEntry; 00096 PHYSICAL_ADDRESS identityAddress; 00097 00098 #if defined(_X86PAE_) 00099 00100 ULONG pageDirectoryPointerTableIndex; 00101 PHARDWARE_PTE pageDirectoryPointerTable; 00102 PHARDWARE_PTE pageDirectoryPointerTableEntry; 00103 00104 #endif 00105 00106 // 00107 // Initialize the IdentityMap structure to a known state. 00108 // 00109 00110 RtlZeroMemory( IdentityMap, sizeof(IDENTITY_MAP) ); 00111 length = (PCHAR)EndVa - (PCHAR)StartVa; 00112 00113 // 00114 // Get the physical address of the input buffer (or suitable copy). 00115 // 00116 00117 identityAddress = Ki386BuildIdentityBuffer( IdentityMap, 00118 StartVa, 00119 length, 00120 &pagesToMap ); 00121 if( identityAddress.QuadPart == 0) { 00122 00123 // 00124 // The input buffer was not contiguous or not below 4G, and a 00125 // suitable buffer could not be allocated. 00126 // 00127 00128 return FALSE; 00129 } 00130 00131 IdentityMap->IdentityAddr = identityAddress.LowPart; 00132 00133 // 00134 // Set up the mappings. 00135 // 00136 00137 currentVa = StartVa; 00138 do { 00139 00140 // 00141 // Map in the virtual address 00142 // 00143 00144 result = Ki386MapAddress( IdentityMap, 00145 (ULONG)currentVa, 00146 identityAddress ); 00147 if (result == FALSE) { 00148 return FALSE; 00149 } 00150 00151 // 00152 // Map in the identity (physical) address 00153 // 00154 00155 result = Ki386MapAddress( IdentityMap, 00156 identityAddress.LowPart, 00157 identityAddress ); 00158 if (result == FALSE) { 00159 return FALSE; 00160 } 00161 00162 // 00163 // Advance both the Va and identityAddress pointers in anticipation 00164 // of mapping in another page. 00165 // 00166 00167 currentVa += PAGE_SIZE; 00168 identityAddress.QuadPart += PAGE_SIZE; 00169 pagesToMap -= 1; 00170 00171 } while (pagesToMap > 0); 00172 00173 // 00174 // Now go through the page directory pointer table and page directories, 00175 // converting virtual page frames to physical ones. 00176 // 00177 00178 #if defined(_X86PAE_) 00179 00180 // 00181 // This PAE-only outer loop walks the page directory pointer table entries 00182 // and processes each valid page directory referenced. 00183 // 00184 00185 pageDirectoryPointerTable = IdentityMap->TopLevelDirectory; 00186 for (pageDirectoryPointerTableIndex = 0; 00187 pageDirectoryPointerTableIndex < (1 << PPI_BITS); 00188 pageDirectoryPointerTableIndex++) { 00189 00190 pageDirectoryPointerTableEntry = 00191 &pageDirectoryPointerTable[ pageDirectoryPointerTableIndex ]; 00192 00193 if (pageDirectoryPointerTableEntry->Valid == 0) { 00194 continue; 00195 } 00196 00197 pageDirectory = 00198 (PHARDWARE_PTE)Ki386ConvertPte( pageDirectoryPointerTableEntry ); 00199 00200 #else 00201 pageDirectory = IdentityMap->TopLevelDirectory; 00202 #endif 00203 00204 for (pageDirectoryIndex = 0; 00205 pageDirectoryIndex < PTES_PER_PAGE; 00206 pageDirectoryIndex++) { 00207 00208 pageDirectoryEntry = &pageDirectory[ pageDirectoryIndex ]; 00209 if (pageDirectoryEntry->Valid == 0) { 00210 continue; 00211 } 00212 00213 Ki386ConvertPte( pageDirectoryEntry ); 00214 } 00215 00216 #if defined(_X86PAE_) 00217 } 00218 #endif 00219 00220 identityAddress = MmGetPhysicalAddress( IdentityMap->TopLevelDirectory ); 00221 IdentityMap->IdentityCR3 = identityAddress.LowPart; 00222 00223 return TRUE; 00224 }

VOID Ki386EnableTargetLargePage IN PIDENTITY_MAP  IdentityMap  ) 
 

Definition at line 673 of file largepag.c.

References Ki386EnableCurrentLargePage().

00676 { 00677 /*++ 00678 00679 This function just passes info on to the assembly routine 00680 Ki386EnableLargePage(). 00681 00682 --*/ 00683 00684 Ki386EnableCurrentLargePage(IdentityMap->IdentityAddr, 00685 IdentityMap->IdentityCR3); 00686 }

BOOLEAN Ki386IdentityMapMakeValid IN OUT PIDENTITY_MAP  IdentityMap,
IN PHARDWARE_PTE  PageTableEntry,
OUT PVOID *Page  OPTIONAL
 

Definition at line 301 of file largepag.c.

References FALSE, Ki386AllocateContiguousMemory(), NULL, PAGE_SHIFT, and TRUE.

Referenced by Ki386MapAddress().

00315 : At this point, PTE frames are virtual. After the entire mapping 00316 is built, we go through and convert all virtual frames to physical 00317 ones. 00318 00319 Arguments: 00320 00321 IdentityMap - Context pointer for this identity mapping. 00322 00323 PageTableEntry - Pointer to the page table entry. 00324 00325 Page - Virtual address now referenced by the PTE, whether it was 00326 valid before or not. 00327 00328 Return Value: 00329 00330 TRUE on success, FALSE otherwise. 00331 00332 --*/ 00333 { 00334 PVOID page; 00335 00336 if (PageTableEntry->Valid != 0) { 00337 00338 // 00339 // If it already is present, there is nothing to do except record 00340 // the virtual page number that is already there. 00341 // 00342 00343 page = (PVOID)((ULONG)(PageTableEntry->PageFrameNumber << PAGE_SHIFT)); 00344 00345 } else { 00346 00347 // 00348 // The page table entry is not valid. Allocate a new page table. 00349 // 00350 00351 page = Ki386AllocateContiguousMemory( IdentityMap, 1, FALSE ); 00352 if (page == NULL) { 00353 return FALSE; 00354 } 00355 00356 // 00357 // Insert it into the page table entry and mark it valid. 00358 // 00359 // NOTE: Virtual page numbers are inserted into the page table 00360 // structure as it is being built. When it is finished, we walk 00361 // the tables and convert all of the virtual page numbers to 00362 // physical page numbers. 00363 // 00364 00365 PageTableEntry->PageFrameNumber = ((ULONG)page) >> PAGE_SHIFT; 00366 PageTableEntry->Valid = 1; 00367 } 00368 00369 if (ARGUMENT_PRESENT( Page )) { 00370 *Page = page; 00371 } 00372 00373 return TRUE; 00374 }

BOOLEAN Ki386MapAddress IN OUT PIDENTITY_MAP  IdentityMap,
IN ULONG  Va,
IN PHYSICAL_ADDRESS  PhysicalAddress
 

Definition at line 377 of file largepag.c.

References FALSE, Ki386AllocateContiguousMemory(), Ki386IdentityMapMakeValid(), KiGetPdeIndex, KiGetPpeIndex, KiGetPteIndex, NULL, PAGE_SHIFT, and TRUE.

Referenced by Ki386CreateIdentityMap().

00387 : 00388 00389 IdentityMap - Context pointer for this identity mapping. 00390 00391 Va - Virtual address to map. 00392 00393 PhysicalAddress - Physical address to map. 00394 00395 Return Value: 00396 00397 TRUE on success, FALSE otherwise. 00398 00399 --*/ 00400 { 00401 PHARDWARE_PTE pageTable; 00402 PHARDWARE_PTE pageTableEntry; 00403 PHARDWARE_PTE pageDirectory; 00404 PHARDWARE_PTE pageDirectoryEntry; 00405 PVOID table; 00406 ULONG index; 00407 BOOLEAN result; 00408 00409 #if defined(_X86PAE_) 00410 PHARDWARE_PTE pageDirectoryPointerTable; 00411 PHARDWARE_PTE pageDirectoryPointerTableEntry; 00412 #endif 00413 00414 if (IdentityMap->TopLevelDirectory == NULL) { 00415 00416 // 00417 // Allocate a top-level directory structure, either a page directory 00418 // or a page directory pointer table. 00419 // 00420 00421 table = Ki386AllocateContiguousMemory( IdentityMap, 1, TRUE ); 00422 if (table == FALSE) { 00423 return FALSE; 00424 } 00425 00426 IdentityMap->TopLevelDirectory = table; 00427 } 00428 00429 #if defined(_X86PAE_) 00430 00431 index = KiGetPpeIndex( Va ); 00432 pageDirectoryPointerTable = IdentityMap->TopLevelDirectory; 00433 pageDirectoryPointerTableEntry = &pageDirectoryPointerTable[ index ]; 00434 00435 result = Ki386IdentityMapMakeValid( IdentityMap, 00436 pageDirectoryPointerTableEntry, 00437 &pageDirectory ); 00438 if (result == FALSE) { 00439 return FALSE; 00440 } 00441 00442 #else 00443 00444 pageDirectory = IdentityMap->TopLevelDirectory; 00445 00446 #endif 00447 00448 // 00449 // Get a pointer to the appropriate page directory entry. If it is 00450 // not valid, allocate a new page table and mark the page directory 00451 // entry valid and writeable. 00452 // 00453 00454 index = KiGetPdeIndex( Va ); 00455 pageDirectoryEntry = &pageDirectory[ index ]; 00456 result = Ki386IdentityMapMakeValid( IdentityMap, 00457 pageDirectoryEntry, 00458 &pageTable ); 00459 if (result == FALSE) { 00460 return FALSE; 00461 } 00462 pageDirectoryEntry->Write = 1; 00463 00464 // 00465 // Get a pointer to the appropriate page table entry and fill it in. 00466 // 00467 00468 index = KiGetPteIndex( Va ); 00469 pageTableEntry = &pageTable[ index ]; 00470 00471 #if defined(_X86PAE_) 00472 pageTableEntry->PageFrameNumber = PhysicalAddress.QuadPart >> PAGE_SHIFT; 00473 #else 00474 pageTableEntry->PageFrameNumber = PhysicalAddress.LowPart >> PAGE_SHIFT; 00475 #endif 00476 pageTableEntry->Valid = 1; 00477 00478 return TRUE; 00479 }


Generated on Sat May 15 19:44:29 2004 for test by doxygen 1.3.7