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 }