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 }