00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
#include "mi.h"
00027 
00028 
00029 
00030 
00031 
00032 
static
00033 ULONG
00034 
MaximumAlignment( ULONG );
00035 
00036 
static
00037 ULONG
00038 
AggregatePages( 
PMMPTE, ULONG, ULONG, PULONG );
00039 
00040 
00041 
00042 
NTSTATUS
00043 MiMapViewOfPhysicalSection (
00044     IN 
PCONTROL_AREA ControlArea,
00045     IN 
PEPROCESS Process,
00046     IN PVOID *CapturedBase,
00047     IN PLARGE_INTEGER SectionOffset,
00048     IN PSIZE_T CapturedViewSize,
00049     IN ULONG ProtectionMask,
00050     IN ULONG_PTR ZeroBits,
00051     IN ULONG AllocationType,
00052     IN BOOLEAN WriteCombined,
00053     OUT PBOOLEAN ReleasedWsMutex
00054     )
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
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     
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     
00121     
00122     
00123     
00124     
00125     
00126     
00127     
00128 
00129     Alignment = 
X64K;
00130 
00131     
if( AllocationType & MEM_LARGE_PAGES ){
00132 
00133         
00134         
00135         
00136         
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         
00159         
00160         
00161 
00162         
try {
00163 
00164             
00165             
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 - 1
L) | (
PAGE_SIZE - 1
L));
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         
00195         
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 - 1
L) | (
PAGE_SIZE - 1
L));
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     
00217     
00218     
00219 
00220     
00221     
00222     
00223     
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         
00252         Vad->
u.VadFlags.Protection = ProtectionMask;
00253         Vad->
u2.VadFlags2.CopyOnWrite = 0;
00254         
00255         Vad->
FirstPrototypePte =
00256                        (
PMMPTE)(
MI_CONVERT_PHYSICAL_BUS_TO_PFN(*SectionOffset));
00257 
00258         
00259         
00260         
00261 
00262         Vad->
LastContiguousPte =
00263                        (
PMMPTE)(
MI_CONVERT_PHYSICAL_BUS_TO_PFN(*SectionOffset));
00264 
00265         
00266         
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             
00281             
00282             
00283             
00284 
00285             
ExFreePool (Vad);
00286             
return GetExceptionCode();
00287         }
00288         
return STATUS_INSUFFICIENT_RESOURCES;
00289     }
00290 
00291     
00292     
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     
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         
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             
00428             
00429             
00430 
00431             
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle);
00432 
00433             PointerPte += 1;
00434 
00435             TempPte.u.Hard.PageFrameNumber += 1;
00436 
00437         } 
00438 
00439     }  
00440 
00441     
UNLOCK_WS_UNSAFE (Process);
00442     *ReleasedWsMutex = 
TRUE;
00443 
00444     
00445     
00446     
00447 
00448     *CapturedViewSize = (ULONG)EndingAddress - (ULONG)StartingAddress + 1
L;
00449     Process->VirtualSize += *CapturedViewSize;
00450 
00451     
if (Process->VirtualSize > Process->PeakVirtualSize) {
00452         Process->PeakVirtualSize = Process->VirtualSize;
00453     }
00454 
00455     
00456     
00457     
00458     
00459     
00460     
00461     
00462     
00463     
00464 
00465     *CapturedBase = HalCreateQva( *SectionOffset, StartingAddress );
00466 
00467     
return STATUS_SUCCESS;
00468 }
00469 
00470 
00471 ULONG
00472 MaximumAlignment(
00473     IN ULONG Offset
00474     )
00475 
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 
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 }
00513 
00514 
00515 ULONG
00516 AggregatePages(
00517     IN 
PMMPTE  PointerPte,
00518     IN ULONG   Pfn,
00519     IN ULONG   Pages,
00520     OUT PULONG GranularityHint
00521     )
00522 
00523 
00524 
00525 
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 
00543 
00544 
00545 
00546 
00547 
00548 {
00549 
00550     ULONG MaxVirtualAlignment;
00551     ULONG MaxPhysicalAlignment;
00552     ULONG MaxPageAlignment;
00553     ULONG MaxAlignment;
00554 
00555     
00556     
00557     
00558     
00559     
00560     
00561     
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     
00579     
00580 
00581     MaxAlignment =  (MaxVirtualAlignment > MaxPhysicalAlignment) ?
00582                         MaxPhysicalAlignment : MaxVirtualAlignment;
00583     MaxAlignment = (MaxAlignment > MaxPageAlignment) ?
00584                         MaxPageAlignment : MaxAlignment;
00585 
00586     
00587     
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     } 
00617 
00618     
00619     
00620     
00621 
00622     
return( MaxAlignment >> 
PAGE_SHIFT );
00623 
00624 }