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

physsect.c File Reference

#include "mi.h"

Go to the source code of this file.

Functions

ULONG MaximumAlignment (ULONG)
ULONG AggregatePages (PMMPTE, ULONG, ULONG, PULONG)
NTSTATUS MiMapViewOfPhysicalSection (IN PCONTROL_AREA ControlArea, IN PEPROCESS Process, IN PVOID *CapturedBase, IN PLARGE_INTEGER SectionOffset, IN PSIZE_T CapturedViewSize, IN ULONG ProtectionMask, IN ULONG_PTR ZeroBits, IN ULONG AllocationType, IN BOOLEAN WriteCombined, OUT PBOOLEAN ReleasedWsMutex)
ULONG MaximumAlignment (IN ULONG Offset)
ULONG AggregatePages (IN PMMPTE PointerPte, IN ULONG Pfn, IN ULONG Pages, OUT PULONG GranularityHint)


Function Documentation

ULONG AggregatePages IN PMMPTE  PointerPte,
IN ULONG  Pfn,
IN ULONG  Pages,
OUT PULONG  GranularityHint
 

Definition at line 516 of file alpha/physsect.c.

References DbgPrint, GH0, GH1, GH1_PAGE_SIZE, GH2, GH2_PAGE_SIZE, GH3, GH3_PAGE_SIZE, MaximumAlignment(), MiGetVirtualAddressMappedByPte, PAGE_SHIFT, and PAGE_SIZE.

00524 : 00525 00526 This routine computes the number of standard size pages that can be 00527 aggregated into a single large page and returns the granularity hint 00528 for that size large page. 00529 00530 Arguments: 00531 00532 PointerPte - Supplies the PTE pointer for the starting virtual address 00533 of the mapping. 00534 Pfn - Supplies the starting page frame number of the memory to be 00535 mapped. 00536 Pages - Supplies the number of pages to map. 00537 00538 GranularityHint - Receives the granularity hint for the large page used 00539 to aggregate the standard pages. 00540 00541 Return Value: 00542 00543 The number of pages that can be aggregated together. 00544 00545 Environment: 00546 00547 --*/ 00548 { 00549 00550 ULONG MaxVirtualAlignment; 00551 ULONG MaxPhysicalAlignment; 00552 ULONG MaxPageAlignment; 00553 ULONG MaxAlignment; 00554 00555 // 00556 // Determine the largest page that will map a maximum of Pages. 00557 // The largest page must be both virtually and physically aligned 00558 // to the large page size boundary. 00559 // Determine the largest common alignment for the virtual and 00560 // physical addresses, factor in Pages, and then match to the 00561 // largest page size possible via the granularity hints. 00562 // 00563 00564 MaxVirtualAlignment = MaximumAlignment((ULONG) 00565 MiGetVirtualAddressMappedByPte( PointerPte ) ); 00566 MaxPhysicalAlignment = MaximumAlignment( (ULONG)(Pfn << PAGE_SHIFT) ); 00567 00568 MaxPageAlignment = (ULONG)(Pages << PAGE_SHIFT); 00569 00570 #ifdef AGGREGATE_DBG 00571 00572 DbgPrint( "MM: Aggregate MaxVirtualAlign = %x\n", MaxVirtualAlignment ); 00573 DbgPrint( "MM: Aggregate MaxPhysicalAlign = %x\n", MaxPhysicalAlignment ); 00574 DbgPrint( "MM: Aggregate MaxPageAlign = %x\n", MaxPageAlignment ); 00575 00576 #endif //AGGREGATE_DBG 00577 // 00578 // Maximum alignment is the minimum of the virtual and physical alignments. 00579 // 00580 00581 MaxAlignment = (MaxVirtualAlignment > MaxPhysicalAlignment) ? 00582 MaxPhysicalAlignment : MaxVirtualAlignment; 00583 MaxAlignment = (MaxAlignment > MaxPageAlignment) ? 00584 MaxPageAlignment : MaxAlignment; 00585 00586 // 00587 // Convert MaxAlignment to granularity hint value 00588 // 00589 00590 if( (MaxAlignment & (GH3_PAGE_SIZE - 1)) == 0 ){ 00591 00592 *GranularityHint = GH3; 00593 00594 } else if( (MaxAlignment & (GH2_PAGE_SIZE - 1)) == 0 ){ 00595 00596 *GranularityHint = GH2; 00597 00598 } else if( (MaxAlignment & (GH1_PAGE_SIZE - 1)) == 0 ){ 00599 00600 *GranularityHint = GH1; 00601 00602 } else if( (MaxAlignment & (PAGE_SIZE - 1)) == 0 ){ 00603 00604 *GranularityHint = GH0; 00605 00606 } else { 00607 00608 *GranularityHint = GH0; 00609 00610 #if DBG 00611 00612 DbgPrint( "MM: Aggregate Physical pages - not page aligned\n" ); 00613 00614 #endif //DBG 00615 00616 } // end, if then elseif 00617 00618 // 00619 // Return number of pages aggregated. 00620 // 00621 00622 return( MaxAlignment >> PAGE_SHIFT ); 00623 00624 } }

ULONG AggregatePages PMMPTE  ,
ULONG  ,
ULONG  ,
PULONG 
[static]
 

ULONG MaximumAlignment IN ULONG  Offset  ) 
 

Definition at line 472 of file alpha/physsect.c.

References GH1_PAGE_SIZE, GH2_PAGE_SIZE, GH3_PAGE_SIZE, Offset, and PAGE_SIZE.

00477 : 00478 00479 This routine returns the maximum granularity hint alignment boundary 00480 to which Offset is naturally aligned. 00481 00482 Arguments: 00483 00484 Offset - Supplies the address offset to check for alignment. 00485 00486 Return Value: 00487 00488 The number which represents the largest natural alignment of Offset. 00489 00490 Environment: 00491 00492 --*/ 00493 { 00494 00495 if( (Offset & (GH3_PAGE_SIZE - 1)) == 0 ){ 00496 return GH3_PAGE_SIZE; 00497 } 00498 00499 if( (Offset & (GH2_PAGE_SIZE - 1)) == 0 ){ 00500 return GH2_PAGE_SIZE; 00501 } 00502 00503 if( (Offset & (GH1_PAGE_SIZE - 1)) == 0 ){ 00504 return GH1_PAGE_SIZE; 00505 } 00506 00507 if( (Offset & (PAGE_SIZE - 1)) == 0 ){ 00508 return PAGE_SIZE; 00509 } 00510 00511 return 0; 00512 }

ULONG MaximumAlignment ULONG   )  [static]
 

NTSTATUS MiMapViewOfPhysicalSection IN PCONTROL_AREA  ControlArea,
IN PEPROCESS  Process,
IN PVOID *  CapturedBase,
IN PLARGE_INTEGER  SectionOffset,
IN PSIZE_T  CapturedViewSize,
IN ULONG  ProtectionMask,
IN ULONG_PTR  ZeroBits,
IN ULONG  AllocationType,
IN BOOLEAN  WriteCombined,
OUT PBOOLEAN  ReleasedWsMutex
 

Definition at line 43 of file alpha/physsect.c.

00058 : 00059 00060 This routine maps the specified physical section into the 00061 specified process's address space. 00062 00063 Arguments: 00064 00065 see MmMapViewOfSection above... 00066 00067 ControlArea - Supplies the control area for the section. 00068 00069 Process - Supplies the process pointer which is receiving the section. 00070 00071 ProtectionMask - Supplies the initial page protection-mask. 00072 00073 ReleasedWsMutex - Supplies FALSE, receives TRUE if the working set 00074 mutex is released. 00075 00076 Return Value: 00077 00078 Status of the map view operation. 00079 00080 Environment: 00081 00082 Kernel Mode, working set mutex and address creation mutex held. 00083 00084 --*/ 00085 00086 { 00087 PMMVAD Vad; 00088 PVOID StartingAddress; 00089 PVOID EndingAddress; 00090 KIRQL OldIrql; 00091 KIRQL OldIrql2; 00092 PMMPTE PointerPpe; 00093 PMMPTE PointerPde; 00094 PMMPTE PointerPte; 00095 PMMPTE LastPte; 00096 MMPTE TempPte; 00097 PMMPFN Pfn2; 00098 ULONG PhysicalViewSize; 00099 ULONG Alignment; 00100 ULONG PagesToMap; 00101 ULONG NextPfn; 00102 PVOID UsedPageTableHandle; 00103 PVOID UsedPageDirectoryHandle; 00104 PMI_PHYSICAL_VIEW PhysicalView; 00105 00106 // 00107 // Physical memory section. 00108 // 00109 00110 #ifdef FIRSTDBG 00111 00112 DbgPrint( "MM: Physsect CaptureBase = %x SectionOffset = %x\n", 00113 CapturedBase, SectionOffset->LowPart ); 00114 DbgPrint( "MM: Physsect Allocation Type = %x, MEM_LARGE_PAGES = %x\n", 00115 AllocationType, MEM_LARGE_PAGES ); 00116 00117 #endif //FIRSTDBG 00118 00119 // 00120 // Compute the alignment we require for the virtual mapping. 00121 // The default is 64K to match protection boundaries. 00122 // Larger page sizes are used if MEM_LARGE_PAGES is requested. 00123 // The Alpha AXP architecture supports granularity hints so that 00124 // larger pages can be defined in the following multiples of 00125 // PAGE_SIZE: 00126 // 8**(GH) * PAGE_SIZE, where GH element of {0,1,2,3} 00127 // 00128 00129 Alignment = X64K; 00130 00131 if( AllocationType & MEM_LARGE_PAGES ){ 00132 00133 // 00134 // MaxAlignment is the maximum boundary alignment of the 00135 // SectionOffset (where the maximum boundary is one of the possible 00136 // granularity hints boundaries) 00137 // 00138 00139 ULONG MaxAlignment = MaximumAlignment( SectionOffset->LowPart ); 00140 00141 Alignment = (MaxAlignment > Alignment) ? MaxAlignment : Alignment; 00142 00143 #ifdef FIRSTDBG 00144 00145 DbgPrint( "MM: Alignment = %x, SectionOffset = %x\n", 00146 Alignment, SectionOffset->LowPart ); 00147 00148 #endif //FIRSTDBG 00149 00150 } 00151 00152 00153 LOCK_WS_UNSAFE (Process); 00154 00155 if (*CapturedBase == NULL) { 00156 00157 // 00158 // Attempt to locate address space. This could raise an 00159 // exception. 00160 // 00161 00162 try { 00163 00164 // 00165 // Find a starting address on an alignment boundary. 00166 // 00167 00168 00169 PhysicalViewSize = (SectionOffset->LowPart + *CapturedViewSize) - 00170 (ULONG)MI_64K_ALIGN(SectionOffset->LowPart); 00171 StartingAddress = MiFindEmptyAddressRange (PhysicalViewSize, 00172 Alignment, 00173 (ULONG)ZeroBits); 00174 00175 } except (EXCEPTION_EXECUTE_HANDLER) { 00176 00177 return GetExceptionCode(); 00178 } 00179 00180 EndingAddress = (PVOID)(((ULONG)StartingAddress + 00181 PhysicalViewSize - 1L) | (PAGE_SIZE - 1L)); 00182 StartingAddress = (PVOID)((ULONG)StartingAddress + 00183 (SectionOffset->LowPart & (X64K - 1))); 00184 00185 if (ZeroBits > 0) { 00186 if (EndingAddress > (PVOID)((ULONG)0xFFFFFFFF >> ZeroBits)) { 00187 return STATUS_NO_MEMORY; 00188 } 00189 } 00190 00191 } else { 00192 00193 // 00194 // Check to make sure the specified base address to ending address 00195 // is currently unused. 00196 // 00197 00198 PhysicalViewSize = (SectionOffset->LowPart + *CapturedViewSize) - 00199 (ULONG)MI_64K_ALIGN(SectionOffset->LowPart); 00200 StartingAddress = (PVOID)((ULONG)MI_64K_ALIGN(*CapturedBase) + 00201 (SectionOffset->LowPart & (X64K - 1))); 00202 EndingAddress = (PVOID)(((ULONG)StartingAddress + 00203 *CapturedViewSize - 1L) | (PAGE_SIZE - 1L)); 00204 00205 Vad = MiCheckForConflictingVad (StartingAddress, EndingAddress); 00206 if (Vad != (PMMVAD)NULL) { 00207 #if 0 00208 MiDumpConflictingVad (StartingAddress, EndingAddress, Vad); 00209 #endif 00210 00211 return STATUS_CONFLICTING_ADDRESSES; 00212 } 00213 } 00214 00215 // 00216 // An unoccuppied address range has been found, build the virtual 00217 // address descriptor to describe this range. 00218 // 00219 00220 // 00221 // Establish an exception handler and attempt to allocate 00222 // the pool and charge quota. Note that the InsertVad routine 00223 // will also charge quota which could raise an exception. 00224 // 00225 00226 try { 00227 00228 PhysicalView = (PMI_PHYSICAL_VIEW)ExAllocatePoolWithTag (NonPagedPool, 00229 sizeof(MI_PHYSICAL_VIEW), 00230 MI_PHYSICAL_VIEW_KEY); 00231 if (PhysicalView == NULL) { 00232 ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES); 00233 } 00234 00235 Vad = (PMMVAD)ExAllocatePoolWithTag (NonPagedPool, sizeof(MMVAD), ' daV'); 00236 if (Vad == NULL) { 00237 ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES); 00238 } 00239 00240 PhysicalView->Vad = Vad; 00241 PhysicalView->StartVa = StartingAddress; 00242 PhysicalView->EndVa = EndingAddress; 00243 00244 Vad->StartingVpn = MI_VA_TO_VPN (StartingAddress); 00245 Vad->EndingVpn = MI_VA_TO_VPN (EndingAddress); 00246 Vad->ControlArea = ControlArea; 00247 Vad->u.LongFlags = 0; 00248 Vad->u2.VadFlags2.Inherit = ViewUnmap; 00249 Vad->u.VadFlags.PhysicalMapping = 1; 00250 Vad->u4.Banked = NULL; 00251 // Vad->u.VadFlags.ImageMap = 0; 00252 Vad->u.VadFlags.Protection = ProtectionMask; 00253 Vad->u2.VadFlags2.CopyOnWrite = 0; 00254 // Vad->u.VadFlags.LargePages = 0; 00255 Vad->FirstPrototypePte = 00256 (PMMPTE)(MI_CONVERT_PHYSICAL_BUS_TO_PFN(*SectionOffset)); 00257 00258 // 00259 // Set the first prototype PTE field in the Vad. 00260 // 00261 00262 Vad->LastContiguousPte = 00263 (PMMPTE)(MI_CONVERT_PHYSICAL_BUS_TO_PFN(*SectionOffset)); 00264 00265 // 00266 // Insert the VAD. This could get an exception. 00267 // 00268 00269 MiInsertVad (Vad); 00270 00271 } except (EXCEPTION_EXECUTE_HANDLER) { 00272 00273 if (PhysicalView != NULL) { 00274 ExFreePool (PhysicalView); 00275 } 00276 00277 if (Vad != (PMMVAD)NULL) { 00278 00279 // 00280 // The pool allocation suceeded, but the quota charge 00281 // in InsertVad failed, deallocate the pool and return 00282 // an error. 00283 // 00284 00285 ExFreePool (Vad); 00286 return GetExceptionCode(); 00287 } 00288 return STATUS_INSUFFICIENT_RESOURCES; 00289 } 00290 00291 // Increment the count of the number of views for the 00292 // section object. This requires the PFN mutex to be held. 00293 // 00294 00295 LOCK_AWE (Process, OldIrql); 00296 LOCK_PFN2 (OldIrql2); 00297 00298 InsertHeadList (&Process->PhysicalVadList, &PhysicalView->ListEntry); 00299 00300 ControlArea->NumberOfMappedViews += 1; 00301 ControlArea->NumberOfUserReferences += 1; 00302 ASSERT (ControlArea->NumberOfSectionReferences != 0); 00303 00304 UNLOCK_PFN2 (OldIrql2); 00305 UNLOCK_AWE (Process, OldIrql); 00306 00307 // 00308 // Build the PTEs in the address space. 00309 // 00310 00311 PointerPpe = MiGetPpeAddress (StartingAddress); 00312 PointerPde = MiGetPdeAddress (StartingAddress); 00313 PointerPte = MiGetPteAddress (StartingAddress); 00314 LastPte = MiGetPteAddress (EndingAddress); 00315 00316 #if defined (_WIN64) 00317 MiMakePpeExistAndMakeValid (PointerPpe, Process, FALSE); 00318 if (PointerPde->u.Long == 0) { 00319 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 00320 ASSERT (MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0); 00321 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 00322 } 00323 #endif 00324 00325 MiMakePdeExistAndMakeValid(PointerPde, Process, FALSE); 00326 00327 Pfn2 = MI_PFN_ELEMENT(PointerPde->u.Hard.PageFrameNumber); 00328 00329 PagesToMap = ( ((ULONG)EndingAddress - (ULONG)StartingAddress) 00330 + (PAGE_SIZE-1) ) >> PAGE_SHIFT; 00331 00332 NextPfn = MI_CONVERT_PHYSICAL_BUS_TO_PFN(*SectionOffset); 00333 00334 #ifdef FIRSTDBG 00335 00336 DbgPrint( "MM: Physsect, PagesToMap = %x NextPfn = %x\n", 00337 PagesToMap, NextPfn ); 00338 00339 #endif //FIRSTDBG 00340 00341 MI_MAKE_VALID_PTE (TempPte, 00342 NextPfn, 00343 ProtectionMask, 00344 PointerPte); 00345 00346 if (WriteCombined == TRUE) { 00347 MI_SET_PTE_WRITE_COMBINE (TempPte); 00348 } 00349 00350 if (TempPte.u.Hard.Write) { 00351 TempPte.u.Hard.Dirty = 1; 00352 } 00353 00354 while (PointerPte <= LastPte) { 00355 00356 ULONG PagesTogether; 00357 ULONG GranularityHint; 00358 00359 // 00360 // Compute the number of pages that can be mapped together 00361 // 00362 00363 if (AllocationType & MEM_LARGE_PAGES) { 00364 PagesTogether = AggregatePages (PointerPte, 00365 NextPfn, 00366 PagesToMap, 00367 &GranularityHint); 00368 } else { 00369 PagesTogether = 1; 00370 GranularityHint = 0; 00371 } 00372 00373 #ifdef FIRSTDBG 00374 00375 DbgPrint( "MM: Physsect PointerPte = %x, NextPfn = %x\n", 00376 PointerPte, NextPfn ); 00377 DbgPrint( "MM: Va = %x TempPte.Pfn = %x\n", 00378 MiGetVirtualAddressMappedByPte( PointerPte ), 00379 TempPte.u.Hard.PageFrameNumber ); 00380 DbgPrint( "MM: PagesToMap = %x\n", PagesToMap ); 00381 DbgPrint( "MM: PagesTogether = %x, GH = %x\n", 00382 PagesTogether, GranularityHint ); 00383 00384 #endif //FIRSTDBG 00385 00386 TempPte.u.Hard.GranularityHint = GranularityHint; 00387 00388 NextPfn += PagesTogether; 00389 PagesToMap -= PagesTogether; 00390 00391 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (MiGetVirtualAddressMappedByPte (PointerPte)); 00392 00393 while (PagesTogether--) { 00394 00395 if (MiIsPteOnPdeBoundary (PointerPte)) { 00396 00397 PointerPde = MiGetPteAddress (PointerPte); 00398 00399 if (MiIsPteOnPpeBoundary (PointerPte)) { 00400 PointerPpe = MiGetPteAddress (PointerPde); 00401 MiMakePpeExistAndMakeValid (PointerPpe, Process, FALSE); 00402 if (PointerPde->u.Long == 0) { 00403 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 00404 ASSERT (MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0); 00405 00406 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 00407 } 00408 } 00409 00410 MiMakePdeExistAndMakeValid (PointerPde, Process, FALSE); 00411 Pfn2 = MI_PFN_ELEMENT (PointerPde->u.Hard.PageFrameNumber); 00412 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (MiGetVirtualAddressMappedByPte (PointerPte)); 00413 } 00414 00415 ASSERT( PointerPte->u.Long == 0 ); 00416 00417 *PointerPte = TempPte; 00418 #if PFN_CONSISTENCY 00419 LOCK_PFN (OldIrql); 00420 #endif 00421 Pfn2->u2.ShareCount += 1; 00422 #if PFN_CONSISTENCY 00423 UNLOCK_PFN (OldIrql); 00424 #endif 00425 00426 // 00427 // Increment the count of non-zero page table entries for this 00428 // page table and the number of private pages for the process. 00429 // 00430 00431 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle); 00432 00433 PointerPte += 1; 00434 00435 TempPte.u.Hard.PageFrameNumber += 1; 00436 00437 } // while (PagesTogether-- ) 00438 00439 } // while (PointerPte <= LastPte) 00440 00441 UNLOCK_WS_UNSAFE (Process); 00442 *ReleasedWsMutex = TRUE; 00443 00444 // 00445 // Update the current virtual size in the process header. 00446 // 00447 00448 *CapturedViewSize = (ULONG)EndingAddress - (ULONG)StartingAddress + 1L; 00449 Process->VirtualSize += *CapturedViewSize; 00450 00451 if (Process->VirtualSize > Process->PeakVirtualSize) { 00452 Process->PeakVirtualSize = Process->VirtualSize; 00453 } 00454 00455 // 00456 // Translate the virtual address to a quasi-virtual address for 00457 // use by drivers that touch mapped devices. Note: the routine 00458 // HalCreateQva will not translate the StartingAddress if the 00459 // StartingAddress is within system memory address space. 00460 // 00461 // N.B. - It will not work to attempt map addresses that begin in 00462 // system memory and extend through i/o space. 00463 // 00464 00465 *CapturedBase = HalCreateQva( *SectionOffset, StartingAddress ); 00466 00467 return STATUS_SUCCESS; 00468 }


Generated on Sat May 15 19:45:02 2004 for test by doxygen 1.3.7