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