00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
#include "mi.h"
00025 
00026 
00027 
00028 
00029 
static
00030 ULONG
00031 
MaximumAlignment(
00032     ULONG Offset
00033     );
00034 
00035 
static
00036 ULONG
00037 
AggregatePages(
00038     
PMMPTE,
00039     PFN_NUMBER,
00040     ULONG,
00041     PULONG
00042     );
00043 
00044 
NTSTATUS
00045 MiMapViewOfPhysicalSection (
00046     IN 
PCONTROL_AREA ControlArea,
00047     IN 
PEPROCESS Process,
00048     IN PVOID *CapturedBase,
00049     IN PLARGE_INTEGER SectionOffset,
00050     IN PSIZE_T CapturedViewSize,
00051     IN ULONG ProtectionMask,
00052     IN ULONG_PTR ZeroBits,
00053     IN ULONG AllocationType,
00054     IN BOOLEAN WriteCombined,
00055     OUT PBOOLEAN ReleasedWsMutex
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 
00088 {
00089     
PMMVAD Vad;
00090     PVOID StartingAddress;
00091     PVOID EndingAddress;
00092     KIRQL OldIrql;
00093     KIRQL OldIrql2;
00094     
PMMPTE PointerPpe;
00095     
PMMPTE PointerPde;
00096     
PMMPTE PointerPte;
00097     
PMMPTE LastPte;
00098     
MMPTE TempPte;
00099     
PMMPFN Pfn2;
00100     SIZE_T PhysicalViewSize;
00101     ULONG Alignment;
00102     ULONG PagesToMap;
00103     PFN_NUMBER NextPfn;
00104     PVOID UsedPageTableHandle;
00105     PVOID UsedPageDirectoryHandle;
00106     
PMI_PHYSICAL_VIEW PhysicalView;
00107 
00108     
00109     
00110     
00111 
00112 
#ifdef FIRSTDBG
00113 
00114     
DbgPrint( 
"MM: Physsect CaptureBase = %x  SectionOffset = %x\n",
00115               CapturedBase, SectionOffset->LowPart );
00116     
DbgPrint( 
"MM: Physsect Allocation Type = %x, MEM_LARGE_PAGES = %x\n",
00117               AllocationType, MEM_LARGE_PAGES );
00118 
00119 
#endif //FIRSTDBG
00120 
00121     
00122     
00123     
00124     
00125     
00126     
00127     
00128     
00129     
00130 
00131     Alignment = 
X64K;
00132 
00133     
if( AllocationType & MEM_LARGE_PAGES ){
00134 
00135         
00136         
00137         
00138         
00139         
00140 
00141         ULONG MaxAlignment = 
MaximumAlignment( SectionOffset->LowPart );
00142 
00143         Alignment = (MaxAlignment > Alignment) ? MaxAlignment : Alignment;
00144 
00145 
#ifdef FIRSTDBG
00146 
00147         
DbgPrint( 
"MM: Alignment = %x, SectionOffset = %x\n",
00148                        Alignment, SectionOffset->LowPart );
00149 
00150 
#endif //FIRSTDBG
00151 
00152     }
00153 
00154 
00155     
LOCK_WS (Process);
00156 
00157     
if (*CapturedBase == 
NULL) {
00158 
00159         
00160         
00161         
00162         
00163 
00164         
try {
00165 
00166             
00167             
00168             
00169 
00170 
00171             PhysicalViewSize = (SectionOffset->LowPart + *CapturedViewSize) -
00172                                (ULONG_PTR)
MI_64K_ALIGN(SectionOffset->LowPart);
00173 
00174             StartingAddress = 
MiFindEmptyAddressRange (PhysicalViewSize,
00175                                                        Alignment,
00176                                                        (ULONG)ZeroBits);
00177 
00178         } except (
EXCEPTION_EXECUTE_HANDLER) {
00179 
00180             
return GetExceptionCode();
00181         }
00182 
00183         EndingAddress = (PVOID)(((ULONG_PTR)StartingAddress +
00184                                 PhysicalViewSize - 1
L) | (
PAGE_SIZE - 1
L));
00185 
00186         StartingAddress = (PVOID)((ULONG_PTR)StartingAddress +
00187                                      (SectionOffset->LowPart & (
X64K - 1)));
00188 
00189         
if (ZeroBits > 0) {
00190             
if (EndingAddress > (PVOID)((LONG_PTR)0xFFFFFFFF >> ZeroBits)) {
00191                 
return STATUS_NO_MEMORY;
00192             }
00193         }
00194 
00195     } 
else {
00196 
00197         
00198         
00199         
00200         
00201 
00202         PhysicalViewSize = (SectionOffset->LowPart + *CapturedViewSize) -
00203                                 (ULONG_PTR)
MI_64K_ALIGN(SectionOffset->LowPart);
00204 
00205         StartingAddress = (PVOID)((ULONG_PTR)
MI_64K_ALIGN(*CapturedBase) +
00206                                     (SectionOffset->LowPart & (
X64K - 1)));
00207 
00208         EndingAddress = (PVOID)(((ULONG_PTR)StartingAddress +
00209                                 *CapturedViewSize - 1
L) | (
PAGE_SIZE - 1
L));
00210 
00211         Vad = 
MiCheckForConflictingVad (StartingAddress, EndingAddress);
00212         
if (Vad != (
PMMVAD)
NULL) {
00213 
#if 0
00214 
            MiDumpConflictingVad (StartingAddress, EndingAddress, Vad);
00215 
#endif
00216 
00217             
return STATUS_CONFLICTING_ADDRESSES;
00218         }
00219     }
00220 
00221     
00222     
00223     
00224     
00225 
00226     
00227     
00228     
00229     
00230     
00231 
00232     
try  {
00233 
00234         PhysicalView = (
PMI_PHYSICAL_VIEW)
ExAllocatePoolWithTag (
NonPagedPool,
00235                                                                  
sizeof(
MI_PHYSICAL_VIEW),
00236                                                                  
MI_PHYSICAL_VIEW_KEY);
00237         
if (PhysicalView == 
NULL) {
00238             
ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
00239         }
00240 
00241         Vad = (
PMMVAD)
ExAllocatePoolWithTag (
NonPagedPool, 
sizeof(
MMVAD), ' daV');
00242         
if (Vad == 
NULL) {
00243             
ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
00244         }
00245 
00246         PhysicalView->
Vad = Vad;
00247         PhysicalView->
StartVa = StartingAddress;
00248         PhysicalView->
EndVa = EndingAddress;
00249 
00250         Vad->
StartingVpn = 
MI_VA_TO_VPN (StartingAddress);
00251         Vad->
EndingVpn = 
MI_VA_TO_VPN (EndingAddress);
00252         Vad->
ControlArea = ControlArea;
00253         Vad->
u.LongFlags = 0;
00254         Vad->
u2.VadFlags2.Inherit = ViewUnmap;
00255         Vad->
u.VadFlags.PhysicalMapping = 1;
00256         Vad->
u4.Banked = 
NULL;
00257         
00258         Vad->
u.VadFlags.Protection = ProtectionMask;
00259         Vad->
u2.VadFlags2.CopyOnWrite = 0;
00260         
00261         Vad->
FirstPrototypePte =
00262                        (
PMMPTE)(
MI_CONVERT_PHYSICAL_BUS_TO_PFN(*SectionOffset));
00263 
00264         
00265         
00266         
00267 
00268         Vad->
LastContiguousPte =
00269                        (
PMMPTE)(
MI_CONVERT_PHYSICAL_BUS_TO_PFN(*SectionOffset));
00270 
00271         
00272         
00273         
00274 
00275         
MiInsertVad (Vad);
00276 
00277     } except (
EXCEPTION_EXECUTE_HANDLER) {
00278 
00279         
if (PhysicalView != 
NULL) {
00280             
ExFreePool (PhysicalView);
00281         }
00282 
00283         
if (Vad != (
PMMVAD)
NULL) {
00284 
00285             
00286             
00287             
00288             
00289             
00290 
00291             
ExFreePool (Vad);
00292             
return GetExceptionCode();
00293         }
00294         
return STATUS_INSUFFICIENT_RESOURCES;
00295     }
00296 
00297     
00298     
00299     
00300 
00301     
LOCK_AWE (Process, OldIrql);
00302     
LOCK_PFN2 (OldIrql2);
00303 
00304     InsertHeadList (&Process->PhysicalVadList, &PhysicalView->
ListEntry);
00305 
00306     ControlArea->NumberOfMappedViews += 1;
00307     ControlArea->NumberOfUserReferences += 1;
00308     
ASSERT (ControlArea->NumberOfSectionReferences != 0);
00309 
00310     
UNLOCK_PFN2 (OldIrql2);
00311     
UNLOCK_AWE (Process, OldIrql);
00312 
00313     
00314     
00315     
00316 
00317     PointerPpe = 
MiGetPpeAddress (StartingAddress);
00318     PointerPde = 
MiGetPdeAddress (StartingAddress);
00319     PointerPte = 
MiGetPteAddress (StartingAddress);
00320     LastPte = 
MiGetPteAddress (EndingAddress);
00321 
00322 
#if defined (_WIN64)
00323 
    MiMakePpeExistAndMakeValid (PointerPpe, Process, 
FALSE);
00324     
if (PointerPde->
u.Long == 0) {
00325         UsedPageDirectoryHandle = 
MI_GET_USED_PTES_HANDLE (PointerPte);
00326         
ASSERT (
MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0); 
00327         
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
00328     }
00329 
#endif
00330 
00331     
MiMakePdeExistAndMakeValid(PointerPde, Process, 
FALSE);
00332 
00333     Pfn2 = 
MI_PFN_ELEMENT(PointerPde->
u.Hard.PageFrameNumber);
00334 
00335     PagesToMap = (ULONG)((((ULONG_PTR)EndingAddress - (ULONG_PTR)StartingAddress))
00336                    + (
PAGE_SIZE-1) ) >> 
PAGE_SHIFT;
00337 
00338     NextPfn = 
MI_CONVERT_PHYSICAL_BUS_TO_PFN(*SectionOffset);
00339 
00340 
#ifdef FIRSTDBG
00341 
00342     
DbgPrint( 
"MM: Physsect, PagesToMap = %x  NextPfn = %x\n",
00343                    PagesToMap, NextPfn );
00344 
00345 
#endif //FIRSTDBG
00346 
00347     
MI_MAKE_VALID_PTE (TempPte,
00348                        NextPfn,
00349                        ProtectionMask,
00350                        PointerPte);
00351 
00352     
if (WriteCombined == 
TRUE) {
00353         
MI_SET_PTE_WRITE_COMBINE (TempPte);
00354     }
00355 
00356     
if (TempPte.
u.Hard.Write) {
00357             TempPte.
u.Hard.FaultOnWrite = 1;
00358     }
00359 
00360     
while (PointerPte <= LastPte) {
00361 
00362         ULONG PagesTogether;
00363         ULONG GranularityHint;
00364 
00365         
00366         
00367         
00368 
00369         
if( AllocationType & MEM_LARGE_PAGES ){
00370             PagesTogether = 
AggregatePages( PointerPte,
00371                                             NextPfn,
00372                                             PagesToMap,
00373                                             &GranularityHint );
00374         } 
else {
00375             PagesTogether = 1;
00376             GranularityHint = 0;
00377         }
00378 
00379 
#ifdef FIRSTDBG
00380 
00381         
DbgPrint( 
"MM: Physsect  PointerPte = %x, NextPfn = %x\n",
00382                        PointerPte, NextPfn );
00383         
DbgPrint( 
"MM: Va = %x  TempPte.Pfn = %x\n",
00384                        
MiGetVirtualAddressMappedByPte( PointerPte ),
00385                        TempPte.
u.Hard.PageFrameNumber );
00386         
DbgPrint( 
"MM: PagesToMap = %x\n", PagesToMap );
00387         
DbgPrint( 
"MM: PagesTogether = %x, GH = %x\n",
00388                        PagesTogether, GranularityHint );
00389 
00390 
#endif //FIRSTDBG
00391 
00392         TempPte.
u.Hard.GranularityHint = GranularityHint;
00393 
00394         NextPfn += PagesTogether;
00395         PagesToMap -= PagesTogether;
00396 
00397         UsedPageTableHandle = 
MI_GET_USED_PTES_HANDLE (
MiGetVirtualAddressMappedByPte (PointerPte));
00398 
00399         
while( PagesTogether-- ){
00400 
00401             
if (
MiIsPteOnPdeBoundary (PointerPte)) {
00402 
00403                 PointerPde = 
MiGetPteAddress (PointerPte);
00404 
00405                 
if (
MiIsPteOnPpeBoundary (PointerPte)) {
00406                     PointerPpe = 
MiGetPteAddress (PointerPde);
00407                     
MiMakePpeExistAndMakeValid (PointerPpe, Process, 
FALSE);
00408                     
if (PointerPde->
u.Long == 0) {
00409                         UsedPageDirectoryHandle = 
MI_GET_USED_PTES_HANDLE (PointerPte);
00410                         
ASSERT (
MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0); 
00411                 
00412                         
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
00413                     }
00414                 }
00415 
00416                 
MiMakePdeExistAndMakeValid (PointerPde, Process, 
FALSE);
00417                 Pfn2 = 
MI_PFN_ELEMENT (PointerPde->
u.Hard.PageFrameNumber);
00418                 UsedPageTableHandle = 
MI_GET_USED_PTES_HANDLE (
MiGetVirtualAddressMappedByPte (PointerPte));
00419             }
00420 
00421             
ASSERT( PointerPte->u.Long == 0 );
00422 
00423             *PointerPte = TempPte;
00424 
#if PFN_CONSISTENCY
00425 
            LOCK_PFN (OldIrql);
00426 
#endif
00427 
            Pfn2->
u2.ShareCount += 1;
00428 
#if PFN_CONSISTENCY
00429 
            UNLOCK_PFN (OldIrql);
00430 
#endif
00431 
00432             
00433             
00434             
00435             
00436 
00437             
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle);
00438 
00439             PointerPte += 1;
00440 
00441             TempPte.u.Hard.PageFrameNumber += 1;
00442 
00443         } 
00444 
00445     }  
00446 
00447     
UNLOCK_WS (Process);
00448     *ReleasedWsMutex = 
TRUE;
00449 
00450     
00451     
00452     
00453 
00454     *CapturedViewSize = (ULONG)((ULONG_PTR)EndingAddress - (ULONG_PTR)StartingAddress + 1
L);
00455     Process->VirtualSize += *CapturedViewSize;
00456 
00457     
if (Process->VirtualSize > Process->PeakVirtualSize) {
00458         Process->PeakVirtualSize = Process->VirtualSize;
00459     }
00460 
00461     
00462     
00463     
00464     
00465     
00466     
00467     
00468     
00469     
00470 
00471     *CapturedBase = HalCreateQva( *SectionOffset, StartingAddress );
00472 
00473     
return STATUS_SUCCESS;
00474 }
00475 
00476 
00477 ULONG
00478 MaximumAlignment(
00479     IN ULONG Offset
00480     )
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491 
00492 
00493 
00494 
00495 
00496 
00497 
00498 
00499 {
00500 
00501     
if( (
Offset & (
GH3_PAGE_SIZE - 1)) == 0 ){
00502         
return GH3_PAGE_SIZE;
00503     }
00504 
00505     
if( (
Offset & (
GH2_PAGE_SIZE - 1)) == 0 ){
00506         
return GH2_PAGE_SIZE;
00507     }
00508 
00509     
if( (
Offset & (
GH1_PAGE_SIZE - 1)) == 0 ){
00510         
return GH1_PAGE_SIZE;
00511     }
00512 
00513     
if( (
Offset & (
PAGE_SIZE - 1)) == 0 ){
00514         
return PAGE_SIZE;
00515     }
00516 
00517     
return 0;
00518 }
00519 
00520 
00521 ULONG
00522 AggregatePages(
00523     IN 
PMMPTE  PointerPte,
00524     IN PFN_NUMBER Pfn,
00525     IN ULONG   Pages,
00526     OUT PULONG GranularityHint
00527     )
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554 {
00555 
00556     ULONG MaxVirtualAlignment;
00557     ULONG MaxPhysicalAlignment;
00558     ULONG MaxPageAlignment;
00559     ULONG MaxAlignment;
00560 
00561     
00562     
00563     
00564     
00565     
00566     
00567     
00568     
00569 
00570     MaxVirtualAlignment =
00571         
MaximumAlignment((ULONG)((ULONG_PTR)
MiGetVirtualAddressMappedByPte(PointerPte)));
00572 
00573     MaxPhysicalAlignment = 
MaximumAlignment( (ULONG)(Pfn << 
PAGE_SHIFT) );
00574 
00575     MaxPageAlignment = (ULONG)(Pages << 
PAGE_SHIFT);
00576 
00577 
#ifdef AGGREGATE_DBG
00578 
00579     
DbgPrint( 
"MM: Aggregate MaxVirtualAlign = %x\n", MaxVirtualAlignment );
00580     
DbgPrint( 
"MM: Aggregate MaxPhysicalAlign = %x\n", MaxPhysicalAlignment );
00581     
DbgPrint( 
"MM: Aggregate MaxPageAlign = %x\n", MaxPageAlignment );
00582 
00583 
#endif //AGGREGATE_DBG
00584 
    
00585     
00586     
00587 
00588     MaxAlignment =  (MaxVirtualAlignment > MaxPhysicalAlignment) ?
00589                         MaxPhysicalAlignment : MaxVirtualAlignment;
00590     MaxAlignment = (MaxAlignment > MaxPageAlignment) ?
00591                         MaxPageAlignment : MaxAlignment;
00592 
00593     
00594     
00595     
00596 
00597     
if( (MaxAlignment & (
GH3_PAGE_SIZE - 1)) == 0 ){
00598 
00599         *GranularityHint = 
GH3;
00600 
00601     } 
else if( (MaxAlignment & (
GH2_PAGE_SIZE - 1)) == 0 ){
00602 
00603         *GranularityHint = 
GH2;
00604 
00605     } 
else if( (MaxAlignment & (
GH1_PAGE_SIZE - 1)) == 0 ){
00606 
00607         *GranularityHint = 
GH1;
00608 
00609     } 
else if( (MaxAlignment & (
PAGE_SIZE - 1)) == 0 ){
00610 
00611         *GranularityHint = 
GH0;
00612 
00613     } 
else {
00614 
00615         *GranularityHint = 
GH0;
00616 
00617 
#if DBG
00618 
00619         
DbgPrint( 
"MM: Aggregate Physical pages - not page aligned\n" );
00620 
00621 
#endif //DBG
00622 
00623     } 
00624 
00625     
00626     
00627     
00628 
00629     
return( MaxAlignment >> 
PAGE_SHIFT );
00630 
00631 }