00035 :
00036
00037 This routine deletes
the specified
virtual address range within
00038
the current process.
00039
00040 Arguments:
00041
00042 StartingAddress - Supplies
the first
virtual address to
delete.
00043
00044 EndingAddress - Supplies
the last address to
delete.
00045
00046 AddressSpaceDeletion - Supplies
TRUE if the address space
is being
00047 deleted,
FALSE otherwise. If
TRUE is specified
00048
the TB
is not flushed and valid addresses are
00049 not removed from
the working set.
00050
00051 Vad - Supplies
the virtual address descriptor which maps
this range
00052 or
NULL if we are not concerned about views. From
the Vad
the
00053 range of prototype PTEs
is determined and
this information
is
00054 used to uncover
if the PTE refers to a prototype PTE or a
00055 fork PTE.
00056
00057 Return Value:
00058
00059 None.
00060
00061
00062 Environment:
00063
00064 Kernel mode, called with APCs disabled, working set mutex and PFN lock
00065 held. These mutexes may be released and reacquired to fault pages in.
00066
00067 --*/
00068
00069 {
00070 PUCHAR Va;
00071 PUCHAR FirstValidVa;
00072 PVOID TempVa;
00073
PMMPTE PointerPte;
00074
PMMPTE PointerPde;
00075
PMMPTE PointerPpe;
00076
PMMPTE OriginalPointerPte;
00077
PMMPTE ProtoPte;
00078
PMMPTE ProtoPte2;
00079
PMMPTE LastProtoPte;
00080
PMMPTE LastProtoPte2;
00081
PEPROCESS CurrentProcess;
00082
PSUBSECTION Subsection;
00083 PVOID UsedPageTableHandle;
00084 PVOID UsedPageDirectoryHandle;
00085 KIRQL OldIrql;
00086
MMPTE_FLUSH_LIST FlushList;
00087 ULONG Waited;
00088 LOGICAL Skipped;
00089
00090 OldIrql =
APC_LEVEL;
00091 FlushList.
Count = 0;
00092
00093
MM_PFN_LOCK_ASSERT();
00094 CurrentProcess =
PsGetCurrentProcess();
00095
00096 Va = StartingAddress;
00097 PointerPpe =
MiGetPpeAddress (Va);
00098 PointerPde =
MiGetPdeAddress (Va);
00099 PointerPte =
MiGetPteAddress (Va);
00100 OriginalPointerPte = PointerPte;
00101
00102
do {
00103
00104
while (
MiDoesPpeExistAndMakeValid (PointerPpe,
00105 CurrentProcess,
00106 TRUE,
00107 &Waited) ==
FALSE) {
00108
00109
00110
00111
00112
00113 PointerPpe += 1;
00114 PointerPde =
MiGetVirtualAddressMappedByPte (PointerPpe);
00115 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00116 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
00117
00118
if (Va > EndingAddress) {
00119
00120
00121
00122
00123
00124
return;
00125 }
00126 }
00127
00128 Waited = 0;
00129
00130
while (
MiDoesPdeExistAndMakeValid (PointerPde,
00131 CurrentProcess,
00132 TRUE,
00133 &Waited) ==
FALSE) {
00134
00135
00136
00137
00138
00139 PointerPde += 1;
00140 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00141 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
00142
00143
if (Va > EndingAddress) {
00144
00145
00146
00147
00148
00149
return;
00150 }
00151
#if defined (_WIN64)
00152
if (
MiIsPteOnPdeBoundary (PointerPde)) {
00153 PointerPpe =
MiGetPteAddress (PointerPde);
00154 Waited = 1;
00155
break;
00156 }
00157
#endif
00158
}
00159
00160 }
while (Waited != 0);
00161
00162 FirstValidVa = Va;
00163 UsedPageTableHandle =
MI_GET_USED_PTES_HANDLE (Va);
00164
00165
00166
00167
00168
00169
if ((Vad == (
PMMVAD)
NULL) ||
00170 (Vad->u.VadFlags.PrivateMemory) ||
00171 (Vad->FirstPrototypePte == (
PMMPTE)
NULL)) {
00172 ProtoPte = (
PMMPTE)
NULL;
00173 LastProtoPte = (
PMMPTE)
NULL;
00174 }
else {
00175 ProtoPte = Vad->FirstPrototypePte;
00176 LastProtoPte = (
PMMPTE)4;
00177 }
00178
00179
00180
00181
00182
00183
while (Va <= EndingAddress) {
00184
00185
00186
00187
00188
00189
00190
if (
MiIsVirtualAddressOnPdeBoundary(Va)) {
00191
00192
00193
00194
00195
00196
00197
00198
MiFlushPteList (&FlushList, FALSE, ZeroPte);
00199
00200
00201
00202
00203
00204
00205
if ((
MI_GET_USED_PTES_FROM_HANDLE (UsedPageTableHandle) == 0) &&
00206 (PointerPde->
u.Long != 0)) {
00207
00208 TempVa =
MiGetVirtualAddressMappedByPte(PointerPde);
00209
MiDeletePte (PointerPde,
00210 TempVa,
00211 AddressSpaceDeletion,
00212 CurrentProcess,
00213 NULL,
00214 NULL);
00215
00216
#if defined (_WIN64)
00217
if (Va == FirstValidVa) {
00218 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
00219 }
00220
else {
00221 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte - 1);
00222 }
00223
00224
MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
00225
#endif
00226
00227 }
00228
00229
if (
MiIsVirtualAddressOnPpeBoundary(Va)) {
00230
00231
if (Va == FirstValidVa) {
00232 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
00233 }
00234
else {
00235 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte - 1);
00236 }
00237
00238
if ((
MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0) &&
00239 (PointerPpe->
u.Long != 0)) {
00240
00241 TempVa =
MiGetVirtualAddressMappedByPte(PointerPpe);
00242
MiDeletePte (PointerPpe,
00243 TempVa,
00244 AddressSpaceDeletion,
00245 CurrentProcess,
00246 NULL,
00247 NULL);
00248 }
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
UNLOCK_PFN (OldIrql);
00260 PointerPde =
MiGetPdeAddress (Va);
00261 PointerPpe =
MiGetPpeAddress (Va);
00262 Skipped =
FALSE;
00263
LOCK_PFN (OldIrql);
00264
00265
do {
00266
while (
MiDoesPpeExistAndMakeValid (PointerPpe,
00267 CurrentProcess,
00268 TRUE,
00269 &Waited) ==
FALSE) {
00270
00271
00272
00273
00274
00275
00276 Skipped =
TRUE;
00277 PointerPpe += 1;
00278 PointerPde =
MiGetVirtualAddressMappedByPte (PointerPpe);
00279 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00280 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
00281
00282
if (Va > EndingAddress) {
00283
00284
00285
00286
00287
00288
return;
00289 }
00290 }
00291
00292 Waited = 0;
00293
00294
while (
MiDoesPdeExistAndMakeValid (PointerPde,
00295 CurrentProcess,
00296 TRUE,
00297 &Waited) ==
FALSE) {
00298
00299
00300
00301
00302
00303 Skipped =
TRUE;
00304 PointerPde += 1;
00305 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00306 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
00307
00308
if (Va > EndingAddress) {
00309
00310
00311
00312
00313
00314
00315
#if defined (_WIN64)
00316
00317 PointerPde -= 1;
00318 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
00319 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
00320
00321
if ((
MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0) &&
00322 (PointerPpe->
u.Long != 0)) {
00323
00324 TempVa =
MiGetVirtualAddressMappedByPte(PointerPpe);
00325
MiDeletePte (PointerPpe,
00326 TempVa,
00327 AddressSpaceDeletion,
00328 CurrentProcess,
00329 NULL,
00330 NULL);
00331 }
00332
#endif
00333
00334
return;
00335 }
00336
00337
#if defined (_WIN64)
00338
if (
MiIsPteOnPdeBoundary (PointerPde)) {
00339 PointerPpe =
MiGetPteAddress (PointerPde);
00340 Waited = 1;
00341
break;
00342 }
00343
#endif
00344
00345
#if DBG
00346
if ((LastProtoPte !=
NULL) &&
00347 (Vad->u2.VadFlags2.ExtendableFile == 0)) {
00348 ProtoPte2 =
MiGetProtoPteAddress(Vad, MI_VA_TO_VPN (Va));
00349 Subsection =
MiLocateSubsection (Vad,MI_VA_TO_VPN (Va));
00350 LastProtoPte2 = &Subsection->
SubsectionBase[Subsection->
PtesInSubsection];
00351
if (Vad->u.VadFlags.ImageMap != 1) {
00352
if ((ProtoPte2 < Subsection->
SubsectionBase) ||
00353 (ProtoPte2 >= LastProtoPte2)) {
00354
DbgPrint (
"bad proto pte %p va %p Vad %p sub %p\n",
00355 ProtoPte2,Va,Vad,Subsection);
00356 DbgBreakPoint();
00357 }
00358 }
00359 }
00360
#endif //DBG
00361
}
00362
00363 }
while (Waited != 0);
00364
00365
00366
00367
00368
00369 UsedPageTableHandle =
MI_GET_USED_PTES_HANDLE (Va);
00370
00371
00372
00373
00374
00375
00376
00377
if ((Skipped ==
TRUE) && (LastProtoPte !=
NULL)) {
00378
00379 ProtoPte =
MiGetProtoPteAddress(Vad,
MI_VA_TO_VPN(Va));
00380 Subsection =
MiLocateSubsection (Vad,
MI_VA_TO_VPN(Va));
00381
00382
if (Subsection !=
NULL) {
00383 LastProtoPte = &Subsection->
SubsectionBase[Subsection->
PtesInSubsection];
00384
#if DBG
00385
if (Vad->u.VadFlags.ImageMap != 1) {
00386
if ((ProtoPte < Subsection->
SubsectionBase) ||
00387 (ProtoPte >= LastProtoPte)) {
00388
DbgPrint (
"bad proto pte %p va %p Vad %p sub %p\n",
00389 ProtoPte,Va,Vad,Subsection);
00390 DbgBreakPoint();
00391 }
00392 }
00393
#endif //DBG
00394
}
00395
else {
00396
00397
00398
00399
00400
00401
00402
00403 LastProtoPte = (
PMMPTE)
NULL;
00404 }
00405 }
00406 }
00407
00408
00409
00410
00411
00412
if (PointerPte->u.Long != 0) {
00413
00414
00415
00416
00417
00418
MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle);
00419
00420
if (
IS_PTE_NOT_DEMAND_ZERO (*PointerPte)) {
00421
00422
if (LastProtoPte !=
NULL) {
00423
if (ProtoPte >= LastProtoPte) {
00424 ProtoPte =
MiGetProtoPteAddress(Vad,
MI_VA_TO_VPN(Va));
00425 Subsection =
MiLocateSubsection (Vad,
MI_VA_TO_VPN(Va));
00426 LastProtoPte = &Subsection->
SubsectionBase[Subsection->
PtesInSubsection];
00427 }
00428
#if DBG
00429
if (Vad->u.VadFlags.ImageMap != 1) {
00430
if ((ProtoPte < Subsection->
SubsectionBase) ||
00431 (ProtoPte >= LastProtoPte)) {
00432
DbgPrint (
"bad proto pte %p va %p Vad %p sub %p\n",
00433 ProtoPte,Va,Vad,Subsection);
00434 DbgBreakPoint();
00435 }
00436 }
00437
#endif //DBG
00438
}
00439
00440
MiDeletePte (PointerPte,
00441 (PVOID)Va,
00442 AddressSpaceDeletion,
00443 CurrentProcess,
00444 ProtoPte,
00445 &FlushList);
00446 }
else {
00447
MI_WRITE_INVALID_PTE (PointerPte, ZeroPte);
00448 }
00449 }
00450
00451 Va +=
PAGE_SIZE;
00452 PointerPte += 1;
00453 ProtoPte += 1;
00454 }
00455
00456
00457
00458
00459
00460
MiFlushPteList (&FlushList, FALSE, ZeroPte);
00461
00462
00463
00464
00465
00466
00467
if ((
MI_GET_USED_PTES_FROM_HANDLE (UsedPageTableHandle) == 0) &&
00468 (PointerPde->
u.Long != 0)) {
00469
00470 TempVa =
MiGetVirtualAddressMappedByPte(PointerPde);
00471
MiDeletePte (PointerPde,
00472 TempVa,
00473 AddressSpaceDeletion,
00474 CurrentProcess,
00475 NULL,
00476 NULL);
00477
00478
#if defined (_WIN64)
00479
UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte - 1);
00480
00481
MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
00482
00483
if ((
MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0) &&
00484 (PointerPpe->
u.Long != 0)) {
00485
00486 TempVa =
MiGetVirtualAddressMappedByPte(PointerPpe);
00487
MiDeletePte (PointerPpe,
00488 TempVa,
00489 AddressSpaceDeletion,
00490 CurrentProcess,
00491 NULL,
00492 NULL);
00493 }
00494
#endif
00495
}
00496
00497
00498
00499
00500
00501
return;
00502 }