00060 :
00061
00062 This routine maps
the specified physical section into
the
00063 specified process's address space.
00064
00065 Arguments:
00066
00067 see
MmMapViewOfSection above...
00068
00069 ControlArea - Supplies
the control area
for the section.
00070
00071 Process - Supplies
the process pointer which
is receiving
the section.
00072
00073 ProtectionMask - Supplies
the initial page protection-mask.
00074
00075 ReleasedWsMutex - Supplies
FALSE, receives
TRUE if the working set
00076 mutex
is released.
00077
00078 Return Value:
00079
00080
Status of
the map view operation.
00081
00082 Environment:
00083
00084 Kernel Mode, working set mutex and address creation mutex held.
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 }