mirror of
https://github.com/reactos/reactos.git
synced 2025-05-29 05:58:13 +00:00
[NTOSKRNL]
Remove all #line 15 "ARM³::BLA" Reasons: - It doesn't provide any benefits, its only purpose was to "look cool" - It never looked cool, instead a character mess appeared - It makes finding the related file harder, especially when the file is named differently then the description or when multiple files have the same tag - It effectively breaks Coverity scans svn path=/trunk/; revision=50149
This commit is contained in:
parent
9db755b143
commit
07bf61809e
25 changed files with 1256 additions and 1281 deletions
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::INIT"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../../ARM3/miarm.h"
|
#include "../../ARM3/miarm.h"
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::CONTMEM"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -32,7 +31,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
ASSERT(SizeInPages != 0);
|
ASSERT(SizeInPages != 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Convert the boundary PFN into an alignment mask
|
// Convert the boundary PFN into an alignment mask
|
||||||
//
|
//
|
||||||
|
@ -40,7 +39,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
|
|
||||||
/* Disable APCs */
|
/* Disable APCs */
|
||||||
KeEnterGuardedRegion();
|
KeEnterGuardedRegion();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop all the physical memory blocks
|
// Loop all the physical memory blocks
|
||||||
//
|
//
|
||||||
|
@ -51,23 +50,23 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
//
|
//
|
||||||
Page = MmPhysicalMemoryBlock->Run[i].BasePage;
|
Page = MmPhysicalMemoryBlock->Run[i].BasePage;
|
||||||
PageCount = MmPhysicalMemoryBlock->Run[i].PageCount;
|
PageCount = MmPhysicalMemoryBlock->Run[i].PageCount;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check how far this memory block will go
|
// Check how far this memory block will go
|
||||||
//
|
//
|
||||||
LastPage = Page + PageCount;
|
LastPage = Page + PageCount;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Trim it down to only the PFNs we're actually interested in
|
// Trim it down to only the PFNs we're actually interested in
|
||||||
//
|
//
|
||||||
if ((LastPage - 1) > HighestPfn) LastPage = HighestPfn + 1;
|
if ((LastPage - 1) > HighestPfn) LastPage = HighestPfn + 1;
|
||||||
if (Page < LowestPfn) Page = LowestPfn;
|
if (Page < LowestPfn) Page = LowestPfn;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Skip this run if it's empty or fails to contain all the pages we need
|
// Skip this run if it's empty or fails to contain all the pages we need
|
||||||
//
|
//
|
||||||
if (!(PageCount) || ((Page + SizeInPages) > LastPage)) continue;
|
if (!(PageCount) || ((Page + SizeInPages) > LastPage)) continue;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now scan all the relevant PFNs in this run
|
// Now scan all the relevant PFNs in this run
|
||||||
//
|
//
|
||||||
|
@ -82,7 +81,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
Length = 0;
|
Length = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// If we haven't chosen a start PFN yet and the caller specified an
|
// If we haven't chosen a start PFN yet and the caller specified an
|
||||||
// alignment, make sure the page matches the alignment restriction
|
// alignment, make sure the page matches the alignment restriction
|
||||||
|
@ -95,7 +94,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
//
|
//
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Increase the number of valid pages, and check if we have enough
|
// Increase the number of valid pages, and check if we have enough
|
||||||
//
|
//
|
||||||
|
@ -106,7 +105,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
//
|
//
|
||||||
Pfn1 -= (Length - 1);
|
Pfn1 -= (Length - 1);
|
||||||
Page -= (Length - 1);
|
Page -= (Length - 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Acquire the PFN lock
|
// Acquire the PFN lock
|
||||||
//
|
//
|
||||||
|
@ -117,7 +116,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
// Things might've changed for us. Is the page still free?
|
// Things might've changed for us. Is the page still free?
|
||||||
//
|
//
|
||||||
if (MiIsPfnInUse(Pfn1)) break;
|
if (MiIsPfnInUse(Pfn1)) break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// So far so good. Is this the last confirmed valid page?
|
// So far so good. Is this the last confirmed valid page?
|
||||||
//
|
//
|
||||||
|
@ -127,7 +126,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
// Sanity check that we didn't go out of bounds
|
// Sanity check that we didn't go out of bounds
|
||||||
//
|
//
|
||||||
ASSERT(i != MmPhysicalMemoryBlock->NumberOfRuns);
|
ASSERT(i != MmPhysicalMemoryBlock->NumberOfRuns);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop until all PFN entries have been processed
|
// Loop until all PFN entries have been processed
|
||||||
//
|
//
|
||||||
|
@ -148,43 +147,43 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
Pfn1->u3.e1.PrototypePte = 0;
|
Pfn1->u3.e1.PrototypePte = 0;
|
||||||
Pfn1->u4.VerifierAllocation = 0;
|
Pfn1->u4.VerifierAllocation = 0;
|
||||||
Pfn1->PteAddress = (PVOID)0xBAADF00D;
|
Pfn1->PteAddress = (PVOID)0xBAADF00D;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is the last PFN, otherwise go on
|
// Check if this is the last PFN, otherwise go on
|
||||||
//
|
//
|
||||||
if (Pfn1 == EndPfn) break;
|
if (Pfn1 == EndPfn) break;
|
||||||
Pfn1--;
|
Pfn1--;
|
||||||
} while (TRUE);
|
} while (TRUE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Mark the first and last PFN so we can find them later
|
// Mark the first and last PFN so we can find them later
|
||||||
//
|
//
|
||||||
Pfn1->u3.e1.StartOfAllocation = 1;
|
Pfn1->u3.e1.StartOfAllocation = 1;
|
||||||
(Pfn1 + SizeInPages - 1)->u3.e1.EndOfAllocation = 1;
|
(Pfn1 + SizeInPages - 1)->u3.e1.EndOfAllocation = 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now it's safe to let go of the PFN lock
|
// Now it's safe to let go of the PFN lock
|
||||||
//
|
//
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Quick sanity check that the last PFN is consistent
|
// Quick sanity check that the last PFN is consistent
|
||||||
//
|
//
|
||||||
EndPfn = Pfn1 + SizeInPages;
|
EndPfn = Pfn1 + SizeInPages;
|
||||||
ASSERT(EndPfn == MI_PFN_ELEMENT(Page + 1));
|
ASSERT(EndPfn == MI_PFN_ELEMENT(Page + 1));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Compute the first page, and make sure it's consistent
|
// Compute the first page, and make sure it's consistent
|
||||||
//
|
//
|
||||||
Page = Page - SizeInPages + 1;
|
Page = Page - SizeInPages + 1;
|
||||||
ASSERT(Pfn1 == MI_PFN_ELEMENT(Page));
|
ASSERT(Pfn1 == MI_PFN_ELEMENT(Page));
|
||||||
ASSERT(Page != 0);
|
ASSERT(Page != 0);
|
||||||
|
|
||||||
/* Enable APCs and return the page */
|
/* Enable APCs and return the page */
|
||||||
KeLeaveGuardedRegion();
|
KeLeaveGuardedRegion();
|
||||||
return Page;
|
return Page;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Keep going. The purpose of this loop is to reconfirm that
|
// Keep going. The purpose of this loop is to reconfirm that
|
||||||
// after acquiring the PFN lock these pages are still usable
|
// after acquiring the PFN lock these pages are still usable
|
||||||
|
@ -192,7 +191,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
Pfn1++;
|
Pfn1++;
|
||||||
Page++;
|
Page++;
|
||||||
} while (TRUE);
|
} while (TRUE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// If we got here, something changed while we hadn't acquired
|
// If we got here, something changed while we hadn't acquired
|
||||||
// the PFN lock yet, so we'll have to restart
|
// the PFN lock yet, so we'll have to restart
|
||||||
|
@ -202,11 +201,11 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (++i != MmPhysicalMemoryBlock->NumberOfRuns);
|
} while (++i != MmPhysicalMemoryBlock->NumberOfRuns);
|
||||||
|
|
||||||
//
|
//
|
||||||
// And if we get here, it means no suitable physical memory runs were found
|
// And if we get here, it means no suitable physical memory runs were found
|
||||||
//
|
//
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PVOID
|
PVOID
|
||||||
|
@ -221,7 +220,7 @@ MiCheckForContiguousMemory(IN PVOID BaseAddress,
|
||||||
{
|
{
|
||||||
PMMPTE StartPte, EndPte;
|
PMMPTE StartPte, EndPte;
|
||||||
PFN_NUMBER PreviousPage = 0, Page, HighPage, BoundaryMask, Pages = 0;
|
PFN_NUMBER PreviousPage = 0, Page, HighPage, BoundaryMask, Pages = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Okay, first of all check if the PFNs match our restrictions
|
// Okay, first of all check if the PFNs match our restrictions
|
||||||
//
|
//
|
||||||
|
@ -229,13 +228,13 @@ MiCheckForContiguousMemory(IN PVOID BaseAddress,
|
||||||
if (LowestPfn + SizeInPages <= LowestPfn) return NULL;
|
if (LowestPfn + SizeInPages <= LowestPfn) return NULL;
|
||||||
if (LowestPfn + SizeInPages - 1 > HighestPfn) return NULL;
|
if (LowestPfn + SizeInPages - 1 > HighestPfn) return NULL;
|
||||||
if (BaseAddressPages < SizeInPages) return NULL;
|
if (BaseAddressPages < SizeInPages) return NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// This is the last page we need to get to and the boundary requested
|
// This is the last page we need to get to and the boundary requested
|
||||||
//
|
//
|
||||||
HighPage = HighestPfn + 1 - SizeInPages;
|
HighPage = HighestPfn + 1 - SizeInPages;
|
||||||
BoundaryMask = ~(BoundaryPfn - 1);
|
BoundaryMask = ~(BoundaryPfn - 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// And here's the PTEs for this allocation. Let's go scan them.
|
// And here's the PTEs for this allocation. Let's go scan them.
|
||||||
//
|
//
|
||||||
|
@ -248,7 +247,7 @@ MiCheckForContiguousMemory(IN PVOID BaseAddress,
|
||||||
//
|
//
|
||||||
ASSERT (StartPte->u.Hard.Valid == 1);
|
ASSERT (StartPte->u.Hard.Valid == 1);
|
||||||
Page = PFN_FROM_PTE(StartPte);
|
Page = PFN_FROM_PTE(StartPte);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Is this the beginning of our adventure?
|
// Is this the beginning of our adventure?
|
||||||
//
|
//
|
||||||
|
@ -271,7 +270,7 @@ MiCheckForContiguousMemory(IN PVOID BaseAddress,
|
||||||
Pages++;
|
Pages++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Have we found all the pages we need by now?
|
// Have we found all the pages we need by now?
|
||||||
// Incidently, this means you only wanted one page
|
// Incidently, this means you only wanted one page
|
||||||
|
@ -297,7 +296,7 @@ MiCheckForContiguousMemory(IN PVOID BaseAddress,
|
||||||
Pages = 0;
|
Pages = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Otherwise, we're still in the game. Do we have all our pages?
|
// Otherwise, we're still in the game. Do we have all our pages?
|
||||||
//
|
//
|
||||||
|
@ -309,7 +308,7 @@ MiCheckForContiguousMemory(IN PVOID BaseAddress,
|
||||||
return MiPteToAddress(StartPte - Pages + 1);
|
return MiPteToAddress(StartPte - Pages + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Try with the next PTE, remember this PFN
|
// Try with the next PTE, remember this PFN
|
||||||
//
|
//
|
||||||
|
@ -317,7 +316,7 @@ MiCheckForContiguousMemory(IN PVOID BaseAddress,
|
||||||
StartPte++;
|
StartPte++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// All good returns are within the loop...
|
// All good returns are within the loop...
|
||||||
//
|
//
|
||||||
|
@ -349,14 +348,14 @@ MiFindContiguousMemory(IN PFN_NUMBER LowestPfn,
|
||||||
SizeInPages,
|
SizeInPages,
|
||||||
CacheType);
|
CacheType);
|
||||||
if (!Page) return NULL;
|
if (!Page) return NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// We'll just piggyback on the I/O memory mapper
|
// We'll just piggyback on the I/O memory mapper
|
||||||
//
|
//
|
||||||
PhysicalAddress.QuadPart = Page << PAGE_SHIFT;
|
PhysicalAddress.QuadPart = Page << PAGE_SHIFT;
|
||||||
BaseAddress = MmMapIoSpace(PhysicalAddress, SizeInPages << PAGE_SHIFT, CacheType);
|
BaseAddress = MmMapIoSpace(PhysicalAddress, SizeInPages << PAGE_SHIFT, CacheType);
|
||||||
ASSERT(BaseAddress);
|
ASSERT(BaseAddress);
|
||||||
|
|
||||||
/* Loop the PFN entries */
|
/* Loop the PFN entries */
|
||||||
Pfn1 = MiGetPfnEntry(Page);
|
Pfn1 = MiGetPfnEntry(Page);
|
||||||
EndPfn = Pfn1 + SizeInPages;
|
EndPfn = Pfn1 + SizeInPages;
|
||||||
|
@ -367,7 +366,7 @@ MiFindContiguousMemory(IN PFN_NUMBER LowestPfn,
|
||||||
Pfn1->PteAddress = PointerPte;
|
Pfn1->PteAddress = PointerPte;
|
||||||
Pfn1->u4.PteFrame = PFN_FROM_PTE(MiAddressToPte(PointerPte++));
|
Pfn1->u4.PteFrame = PFN_FROM_PTE(MiAddressToPte(PointerPte++));
|
||||||
} while (++Pfn1 < EndPfn);
|
} while (++Pfn1 < EndPfn);
|
||||||
|
|
||||||
/* Return the address */
|
/* Return the address */
|
||||||
return BaseAddress;
|
return BaseAddress;
|
||||||
}
|
}
|
||||||
|
@ -389,12 +388,12 @@ MiAllocateContiguousMemory(IN SIZE_T NumberOfBytes,
|
||||||
//
|
//
|
||||||
ASSERT(NumberOfBytes != 0);
|
ASSERT(NumberOfBytes != 0);
|
||||||
ASSERT(CacheType <= MmWriteCombined);
|
ASSERT(CacheType <= MmWriteCombined);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Compute size requested
|
// Compute size requested
|
||||||
//
|
//
|
||||||
SizeInPages = BYTES_TO_PAGES(NumberOfBytes);
|
SizeInPages = BYTES_TO_PAGES(NumberOfBytes);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Convert the cache attribute and check for cached requests
|
// Convert the cache attribute and check for cached requests
|
||||||
//
|
//
|
||||||
|
@ -409,7 +408,7 @@ MiAllocateContiguousMemory(IN SIZE_T NumberOfBytes,
|
||||||
NumberOfBytes,
|
NumberOfBytes,
|
||||||
'mCmM');
|
'mCmM');
|
||||||
if (BaseAddress)
|
if (BaseAddress)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Now make sure it's actually contiguous (if it came from expansion
|
// Now make sure it's actually contiguous (if it came from expansion
|
||||||
// it might not be).
|
// it might not be).
|
||||||
|
@ -427,20 +426,20 @@ MiAllocateContiguousMemory(IN SIZE_T NumberOfBytes,
|
||||||
//
|
//
|
||||||
return BaseAddress;
|
return BaseAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// No such luck
|
// No such luck
|
||||||
//
|
//
|
||||||
ExFreePool(BaseAddress);
|
ExFreePool(BaseAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// According to MSDN, the system won't try anything else if you're higher
|
// According to MSDN, the system won't try anything else if you're higher
|
||||||
// than APC level.
|
// than APC level.
|
||||||
//
|
//
|
||||||
if (KeGetCurrentIrql() > APC_LEVEL) return NULL;
|
if (KeGetCurrentIrql() > APC_LEVEL) return NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Otherwise, we'll go try to find some
|
// Otherwise, we'll go try to find some
|
||||||
//
|
//
|
||||||
|
@ -460,7 +459,7 @@ MiFreeContiguousMemory(IN PVOID BaseAddress)
|
||||||
PMMPFN Pfn1, StartPfn;
|
PMMPFN Pfn1, StartPfn;
|
||||||
PMMPTE PointerPte;
|
PMMPTE PointerPte;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
//
|
//
|
||||||
// First, check if the memory came from initial nonpaged pool, or expansion
|
// First, check if the memory came from initial nonpaged pool, or expansion
|
||||||
//
|
//
|
||||||
|
@ -476,15 +475,15 @@ MiFreeContiguousMemory(IN PVOID BaseAddress)
|
||||||
ExFreePool(BaseAddress);
|
ExFreePool(BaseAddress);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the PTE and frame number for the allocation*/
|
/* Get the PTE and frame number for the allocation*/
|
||||||
PointerPte = MiAddressToPte(BaseAddress);
|
PointerPte = MiAddressToPte(BaseAddress);
|
||||||
PageFrameIndex = PFN_FROM_PTE(PointerPte);
|
PageFrameIndex = PFN_FROM_PTE(PointerPte);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now get the PFN entry for this, and make sure it's the correct one
|
// Now get the PFN entry for this, and make sure it's the correct one
|
||||||
//
|
//
|
||||||
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
||||||
if ((!Pfn1) || (Pfn1->u3.e1.StartOfAllocation == 0))
|
if ((!Pfn1) || (Pfn1->u3.e1.StartOfAllocation == 0))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -496,13 +495,13 @@ MiFreeContiguousMemory(IN PVOID BaseAddress)
|
||||||
0,
|
0,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now this PFN isn't the start of any allocation anymore, it's going out
|
// Now this PFN isn't the start of any allocation anymore, it's going out
|
||||||
//
|
//
|
||||||
StartPfn = Pfn1;
|
StartPfn = Pfn1;
|
||||||
Pfn1->u3.e1.StartOfAllocation = 0;
|
Pfn1->u3.e1.StartOfAllocation = 0;
|
||||||
|
|
||||||
/* Loop the PFNs until we find the one that marks the end of the allocation */
|
/* Loop the PFNs until we find the one that marks the end of the allocation */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -513,35 +512,35 @@ MiFreeContiguousMemory(IN PVOID BaseAddress)
|
||||||
ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
|
ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
|
||||||
ASSERT(Pfn1->u4.VerifierAllocation == 0);
|
ASSERT(Pfn1->u4.VerifierAllocation == 0);
|
||||||
ASSERT(Pfn1->u3.e1.PrototypePte == 0);
|
ASSERT(Pfn1->u3.e1.PrototypePte == 0);
|
||||||
|
|
||||||
/* Set the special pending delete marker */
|
/* Set the special pending delete marker */
|
||||||
MI_SET_PFN_DELETED(Pfn1);
|
MI_SET_PFN_DELETED(Pfn1);
|
||||||
|
|
||||||
/* Keep going for assertions */
|
/* Keep going for assertions */
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
} while (Pfn1++->u3.e1.EndOfAllocation == 0);
|
} while (Pfn1++->u3.e1.EndOfAllocation == 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Found it, unmark it
|
// Found it, unmark it
|
||||||
//
|
//
|
||||||
Pfn1--;
|
Pfn1--;
|
||||||
Pfn1->u3.e1.EndOfAllocation = 0;
|
Pfn1->u3.e1.EndOfAllocation = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now compute how many pages this represents
|
// Now compute how many pages this represents
|
||||||
//
|
//
|
||||||
PageCount = (ULONG)(Pfn1 - StartPfn + 1);
|
PageCount = (ULONG)(Pfn1 - StartPfn + 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// So we can know how much to unmap (recall we piggyback on I/O mappings)
|
// So we can know how much to unmap (recall we piggyback on I/O mappings)
|
||||||
//
|
//
|
||||||
MmUnmapIoSpace(BaseAddress, PageCount << PAGE_SHIFT);
|
MmUnmapIoSpace(BaseAddress, PageCount << PAGE_SHIFT);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Lock the PFN database
|
// Lock the PFN database
|
||||||
//
|
//
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop all the pages
|
// Loop all the pages
|
||||||
//
|
//
|
||||||
|
@ -552,7 +551,7 @@ MiFreeContiguousMemory(IN PVOID BaseAddress)
|
||||||
/* Decrement the share count and move on */
|
/* Decrement the share count and move on */
|
||||||
MiDecrementShareCount(Pfn1++, PageFrameIndex++);
|
MiDecrementShareCount(Pfn1++, PageFrameIndex++);
|
||||||
} while (PageFrameIndex < LastPage);
|
} while (PageFrameIndex < LastPage);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the PFN lock
|
// Release the PFN lock
|
||||||
//
|
//
|
||||||
|
@ -579,33 +578,33 @@ MmAllocateContiguousMemorySpecifyCache(IN SIZE_T NumberOfBytes,
|
||||||
//
|
//
|
||||||
ASSERT(NumberOfBytes != 0);
|
ASSERT(NumberOfBytes != 0);
|
||||||
ASSERT(CacheType <= MmWriteCombined);
|
ASSERT(CacheType <= MmWriteCombined);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Convert the lowest address into a PFN
|
// Convert the lowest address into a PFN
|
||||||
//
|
//
|
||||||
LowestPfn = (PFN_NUMBER)(LowestAcceptableAddress.QuadPart >> PAGE_SHIFT);
|
LowestPfn = (PFN_NUMBER)(LowestAcceptableAddress.QuadPart >> PAGE_SHIFT);
|
||||||
if (BYTE_OFFSET(LowestAcceptableAddress.LowPart)) LowestPfn++;
|
if (BYTE_OFFSET(LowestAcceptableAddress.LowPart)) LowestPfn++;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Convert and validate the boundary address into a PFN
|
// Convert and validate the boundary address into a PFN
|
||||||
//
|
//
|
||||||
if (BYTE_OFFSET(BoundaryAddressMultiple.LowPart)) return NULL;
|
if (BYTE_OFFSET(BoundaryAddressMultiple.LowPart)) return NULL;
|
||||||
BoundaryPfn = (PFN_NUMBER)(BoundaryAddressMultiple.QuadPart >> PAGE_SHIFT);
|
BoundaryPfn = (PFN_NUMBER)(BoundaryAddressMultiple.QuadPart >> PAGE_SHIFT);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Convert the highest address into a PFN
|
// Convert the highest address into a PFN
|
||||||
//
|
//
|
||||||
HighestPfn = (PFN_NUMBER)(HighestAcceptableAddress.QuadPart >> PAGE_SHIFT);
|
HighestPfn = (PFN_NUMBER)(HighestAcceptableAddress.QuadPart >> PAGE_SHIFT);
|
||||||
if (HighestPfn > MmHighestPhysicalPage) HighestPfn = MmHighestPhysicalPage;
|
if (HighestPfn > MmHighestPhysicalPage) HighestPfn = MmHighestPhysicalPage;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Validate the PFN bounds
|
// Validate the PFN bounds
|
||||||
//
|
//
|
||||||
if (LowestPfn > HighestPfn) return NULL;
|
if (LowestPfn > HighestPfn) return NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Let the contiguous memory allocator handle it
|
// Let the contiguous memory allocator handle it
|
||||||
//
|
//
|
||||||
return MiAllocateContiguousMemory(NumberOfBytes,
|
return MiAllocateContiguousMemory(NumberOfBytes,
|
||||||
LowestPfn,
|
LowestPfn,
|
||||||
HighestPfn,
|
HighestPfn,
|
||||||
|
@ -633,10 +632,10 @@ MmAllocateContiguousMemory(IN SIZE_T NumberOfBytes,
|
||||||
//
|
//
|
||||||
HighestPfn = (PFN_NUMBER)(HighestAcceptableAddress.QuadPart >> PAGE_SHIFT);
|
HighestPfn = (PFN_NUMBER)(HighestAcceptableAddress.QuadPart >> PAGE_SHIFT);
|
||||||
if (HighestPfn > MmHighestPhysicalPage) HighestPfn = MmHighestPhysicalPage;
|
if (HighestPfn > MmHighestPhysicalPage) HighestPfn = MmHighestPhysicalPage;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Let the contiguous memory allocator handle it
|
// Let the contiguous memory allocator handle it
|
||||||
//
|
//
|
||||||
return MiAllocateContiguousMemory(NumberOfBytes, 0, HighestPfn, 0, MmCached);
|
return MiAllocateContiguousMemory(NumberOfBytes, 0, HighestPfn, 0, MmCached);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::DRVMGMT"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -91,18 +90,18 @@ MmAddVerifierThunks(IN PVOID ThunkBuffer,
|
||||||
ULONG i;
|
ULONG i;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make sure the driver verifier is initialized
|
// Make sure the driver verifier is initialized
|
||||||
//
|
//
|
||||||
if (!MiVerifierDriverAddedThunkListHead.Flink) return STATUS_NOT_SUPPORTED;
|
if (!MiVerifierDriverAddedThunkListHead.Flink) return STATUS_NOT_SUPPORTED;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the thunk pairs and count them
|
// Get the thunk pairs and count them
|
||||||
//
|
//
|
||||||
ThunkCount = ThunkBufferSize / sizeof(DRIVER_VERIFIER_THUNK_PAIRS);
|
ThunkCount = ThunkBufferSize / sizeof(DRIVER_VERIFIER_THUNK_PAIRS);
|
||||||
if (!ThunkCount) return STATUS_INVALID_PARAMETER_1;
|
if (!ThunkCount) return STATUS_INVALID_PARAMETER_1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now allocate our own thunk table
|
// Now allocate our own thunk table
|
||||||
//
|
//
|
||||||
|
@ -112,7 +111,7 @@ MmAddVerifierThunks(IN PVOID ThunkBuffer,
|
||||||
sizeof(DRIVER_VERIFIER_THUNK_PAIRS),
|
sizeof(DRIVER_VERIFIER_THUNK_PAIRS),
|
||||||
'tVmM');
|
'tVmM');
|
||||||
if (!DriverThunks) return STATUS_INSUFFICIENT_RESOURCES;
|
if (!DriverThunks) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now copy the driver-fed part
|
// Now copy the driver-fed part
|
||||||
//
|
//
|
||||||
|
@ -120,7 +119,7 @@ MmAddVerifierThunks(IN PVOID ThunkBuffer,
|
||||||
RtlCopyMemory(ThunkTable,
|
RtlCopyMemory(ThunkTable,
|
||||||
ThunkBuffer,
|
ThunkBuffer,
|
||||||
ThunkCount * sizeof(DRIVER_VERIFIER_THUNK_PAIRS));
|
ThunkCount * sizeof(DRIVER_VERIFIER_THUNK_PAIRS));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Acquire the system load lock
|
// Acquire the system load lock
|
||||||
//
|
//
|
||||||
|
@ -130,7 +129,7 @@ MmAddVerifierThunks(IN PVOID ThunkBuffer,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the loader entry
|
// Get the loader entry
|
||||||
//
|
//
|
||||||
|
@ -143,13 +142,13 @@ MmAddVerifierThunks(IN PVOID ThunkBuffer,
|
||||||
Status = STATUS_INVALID_PARAMETER_2;
|
Status = STATUS_INVALID_PARAMETER_2;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get driver base and end
|
// Get driver base and end
|
||||||
//
|
//
|
||||||
ModuleBase = LdrEntry->DllBase;
|
ModuleBase = LdrEntry->DllBase;
|
||||||
ModuleEnd = (PVOID)((ULONG_PTR)LdrEntry->DllBase + LdrEntry->SizeOfImage);
|
ModuleEnd = (PVOID)((ULONG_PTR)LdrEntry->DllBase + LdrEntry->SizeOfImage);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Don't allow hooking the kernel or HAL
|
// Don't allow hooking the kernel or HAL
|
||||||
//
|
//
|
||||||
|
@ -161,7 +160,7 @@ MmAddVerifierThunks(IN PVOID ThunkBuffer,
|
||||||
Status = STATUS_INVALID_PARAMETER_2;
|
Status = STATUS_INVALID_PARAMETER_2;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop all the thunks
|
// Loop all the thunks
|
||||||
//
|
//
|
||||||
|
@ -180,7 +179,7 @@ MmAddVerifierThunks(IN PVOID ThunkBuffer,
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Otherwise, add this entry
|
// Otherwise, add this entry
|
||||||
//
|
//
|
||||||
|
@ -190,14 +189,14 @@ MmAddVerifierThunks(IN PVOID ThunkBuffer,
|
||||||
InsertTailList(&MiVerifierDriverAddedThunkListHead,
|
InsertTailList(&MiVerifierDriverAddedThunkListHead,
|
||||||
&DriverThunks->ListEntry);
|
&DriverThunks->ListEntry);
|
||||||
DriverThunks = NULL;
|
DriverThunks = NULL;
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
//
|
//
|
||||||
// Release the lock
|
// Release the lock
|
||||||
//
|
//
|
||||||
KeReleaseMutant(&MmSystemLoadLock, 1, FALSE, FALSE);
|
KeReleaseMutant(&MmSystemLoadLock, 1, FALSE, FALSE);
|
||||||
KeLeaveCriticalRegion();
|
KeLeaveCriticalRegion();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Free the table if we failed and return status
|
// Free the table if we failed and return status
|
||||||
//
|
//
|
||||||
|
@ -213,13 +212,13 @@ NTAPI
|
||||||
MmIsDriverVerifying(IN PDRIVER_OBJECT DriverObject)
|
MmIsDriverVerifying(IN PDRIVER_OBJECT DriverObject)
|
||||||
{
|
{
|
||||||
PLDR_DATA_TABLE_ENTRY LdrEntry;
|
PLDR_DATA_TABLE_ENTRY LdrEntry;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the loader entry
|
// Get the loader entry
|
||||||
//
|
//
|
||||||
LdrEntry = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection;
|
LdrEntry = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection;
|
||||||
if (!LdrEntry) return FALSE;
|
if (!LdrEntry) return FALSE;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we're verifying or not
|
// Check if we're verifying or not
|
||||||
//
|
//
|
||||||
|
@ -244,7 +243,7 @@ MmIsVerifierEnabled(OUT PULONG VerifierFlags)
|
||||||
*VerifierFlags = MmVerifierData.Level;
|
*VerifierFlags = MmVerifierData.Level;
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Otherwise, we're disabled
|
// Otherwise, we're disabled
|
||||||
//
|
//
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::DYNAMIC"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -74,7 +73,7 @@ NTAPI
|
||||||
MmGetPhysicalMemoryRanges(VOID)
|
MmGetPhysicalMemoryRanges(VOID)
|
||||||
{
|
{
|
||||||
ULONG Size, i;
|
ULONG Size, i;
|
||||||
PPHYSICAL_MEMORY_RANGE Entry, Buffer;
|
PPHYSICAL_MEMORY_RANGE Entry, Buffer;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||||
|
|
||||||
|
@ -82,7 +81,7 @@ MmGetPhysicalMemoryRanges(VOID)
|
||||||
// Calculate how much memory we'll need
|
// Calculate how much memory we'll need
|
||||||
//
|
//
|
||||||
Size = sizeof(PHYSICAL_MEMORY_RANGE) * (MmPhysicalMemoryBlock->NumberOfRuns + 1);
|
Size = sizeof(PHYSICAL_MEMORY_RANGE) * (MmPhysicalMemoryBlock->NumberOfRuns + 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate a copy
|
// Allocate a copy
|
||||||
//
|
//
|
||||||
|
@ -93,13 +92,13 @@ MmGetPhysicalMemoryRanges(VOID)
|
||||||
// Lock the PFN database
|
// Lock the PFN database
|
||||||
//
|
//
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make sure it hasn't changed before we had acquired the lock
|
// Make sure it hasn't changed before we had acquired the lock
|
||||||
//
|
//
|
||||||
ASSERT(Size == (sizeof(PHYSICAL_MEMORY_RANGE) *
|
ASSERT(Size == (sizeof(PHYSICAL_MEMORY_RANGE) *
|
||||||
(MmPhysicalMemoryBlock->NumberOfRuns + 1)));
|
(MmPhysicalMemoryBlock->NumberOfRuns + 1)));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now loop our block
|
// Now loop our block
|
||||||
//
|
//
|
||||||
|
@ -112,7 +111,7 @@ MmGetPhysicalMemoryRanges(VOID)
|
||||||
Entry->NumberOfBytes.QuadPart = MmPhysicalMemoryBlock->Run[i].PageCount << PAGE_SHIFT;
|
Entry->NumberOfBytes.QuadPart = MmPhysicalMemoryBlock->Run[i].PageCount << PAGE_SHIFT;
|
||||||
Entry++;
|
Entry++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Last entry is empty
|
// Last entry is empty
|
||||||
//
|
//
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::EXPOOL"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -53,14 +52,14 @@ PKGUARDED_MUTEX ExpPagedPoolMutex;
|
||||||
*/
|
*/
|
||||||
PLIST_ENTRY
|
PLIST_ENTRY
|
||||||
NTAPI
|
NTAPI
|
||||||
ExpDecodePoolLink(IN PLIST_ENTRY Link)
|
ExpDecodePoolLink(IN PLIST_ENTRY Link)
|
||||||
{
|
{
|
||||||
return (PLIST_ENTRY)((ULONG_PTR)Link & ~1);
|
return (PLIST_ENTRY)((ULONG_PTR)Link & ~1);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLIST_ENTRY
|
PLIST_ENTRY
|
||||||
NTAPI
|
NTAPI
|
||||||
ExpEncodePoolLink(IN PLIST_ENTRY Link)
|
ExpEncodePoolLink(IN PLIST_ENTRY Link)
|
||||||
{
|
{
|
||||||
return (PLIST_ENTRY)((ULONG_PTR)Link | 1);
|
return (PLIST_ENTRY)((ULONG_PTR)Link | 1);
|
||||||
}
|
}
|
||||||
|
@ -104,7 +103,7 @@ ExpRemovePoolEntryList(IN PLIST_ENTRY Entry)
|
||||||
Flink->Blink = ExpEncodePoolLink(Blink);
|
Flink->Blink = ExpEncodePoolLink(Blink);
|
||||||
Blink->Flink = ExpEncodePoolLink(Flink);
|
Blink->Flink = ExpEncodePoolLink(Flink);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLIST_ENTRY
|
PLIST_ENTRY
|
||||||
NTAPI
|
NTAPI
|
||||||
ExpRemovePoolHeadList(IN PLIST_ENTRY ListHead)
|
ExpRemovePoolHeadList(IN PLIST_ENTRY ListHead)
|
||||||
|
@ -170,7 +169,7 @@ ExpCheckPoolHeader(IN PPOOL_HEADER Entry)
|
||||||
{
|
{
|
||||||
/* Get it */
|
/* Get it */
|
||||||
PreviousEntry = POOL_PREV_BLOCK(Entry);
|
PreviousEntry = POOL_PREV_BLOCK(Entry);
|
||||||
|
|
||||||
/* The two blocks must be on the same page! */
|
/* The two blocks must be on the same page! */
|
||||||
if (PAGE_ALIGN(Entry) != PAGE_ALIGN(PreviousEntry))
|
if (PAGE_ALIGN(Entry) != PAGE_ALIGN(PreviousEntry))
|
||||||
{
|
{
|
||||||
|
@ -251,31 +250,31 @@ ExpCheckPoolBlocks(IN PVOID Block)
|
||||||
BOOLEAN FoundBlock = FALSE;
|
BOOLEAN FoundBlock = FALSE;
|
||||||
SIZE_T Size = 0;
|
SIZE_T Size = 0;
|
||||||
PPOOL_HEADER Entry;
|
PPOOL_HEADER Entry;
|
||||||
|
|
||||||
/* Get the first entry for this page, make sure it really is the first */
|
/* Get the first entry for this page, make sure it really is the first */
|
||||||
Entry = PAGE_ALIGN(Block);
|
Entry = PAGE_ALIGN(Block);
|
||||||
ASSERT(Entry->PreviousSize == 0);
|
ASSERT(Entry->PreviousSize == 0);
|
||||||
|
|
||||||
/* Now scan each entry */
|
/* Now scan each entry */
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
/* When we actually found our block, remember this */
|
/* When we actually found our block, remember this */
|
||||||
if (Entry == Block) FoundBlock = TRUE;
|
if (Entry == Block) FoundBlock = TRUE;
|
||||||
|
|
||||||
/* Now validate this block header */
|
/* Now validate this block header */
|
||||||
ExpCheckPoolHeader(Entry);
|
ExpCheckPoolHeader(Entry);
|
||||||
|
|
||||||
/* And go to the next one, keeping track of our size */
|
/* And go to the next one, keeping track of our size */
|
||||||
Size += Entry->BlockSize;
|
Size += Entry->BlockSize;
|
||||||
Entry = POOL_NEXT_BLOCK(Entry);
|
Entry = POOL_NEXT_BLOCK(Entry);
|
||||||
|
|
||||||
/* If we hit the last block, stop */
|
/* If we hit the last block, stop */
|
||||||
if (Size >= (PAGE_SIZE / POOL_BLOCK_SIZE)) break;
|
if (Size >= (PAGE_SIZE / POOL_BLOCK_SIZE)) break;
|
||||||
|
|
||||||
/* If we hit the end of the page, stop */
|
/* If we hit the end of the page, stop */
|
||||||
if (PAGE_ALIGN(Entry) == Entry) break;
|
if (PAGE_ALIGN(Entry) == Entry) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We must've found our block, and we must have hit the end of the page */
|
/* We must've found our block, and we must have hit the end of the page */
|
||||||
if ((PAGE_ALIGN(Entry) != Entry) || !(FoundBlock))
|
if ((PAGE_ALIGN(Entry) != Entry) || !(FoundBlock))
|
||||||
{
|
{
|
||||||
|
@ -304,7 +303,7 @@ ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor,
|
||||||
PoolDescriptor->PoolIndex = PoolIndex;
|
PoolDescriptor->PoolIndex = PoolIndex;
|
||||||
PoolDescriptor->Threshold = Threshold;
|
PoolDescriptor->Threshold = Threshold;
|
||||||
PoolDescriptor->LockAddress = PoolLock;
|
PoolDescriptor->LockAddress = PoolLock;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize accounting data
|
// Initialize accounting data
|
||||||
//
|
//
|
||||||
|
@ -313,18 +312,18 @@ ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor,
|
||||||
PoolDescriptor->TotalPages = 0;
|
PoolDescriptor->TotalPages = 0;
|
||||||
PoolDescriptor->TotalBytes = 0;
|
PoolDescriptor->TotalBytes = 0;
|
||||||
PoolDescriptor->TotalBigPages = 0;
|
PoolDescriptor->TotalBigPages = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Nothing pending for now
|
// Nothing pending for now
|
||||||
//
|
//
|
||||||
PoolDescriptor->PendingFrees = NULL;
|
PoolDescriptor->PendingFrees = NULL;
|
||||||
PoolDescriptor->PendingFreeDepth = 0;
|
PoolDescriptor->PendingFreeDepth = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop all the descriptor's allocation lists and initialize them
|
// Loop all the descriptor's allocation lists and initialize them
|
||||||
//
|
//
|
||||||
NextEntry = PoolDescriptor->ListHeads;
|
NextEntry = PoolDescriptor->ListHeads;
|
||||||
LastEntry = NextEntry + POOL_LISTS_PER_PAGE;
|
LastEntry = NextEntry + POOL_LISTS_PER_PAGE;
|
||||||
while (NextEntry < LastEntry)
|
while (NextEntry < LastEntry)
|
||||||
{
|
{
|
||||||
ExpInitializePoolListHead(NextEntry);
|
ExpInitializePoolListHead(NextEntry);
|
||||||
|
@ -339,7 +338,7 @@ InitializePool(IN POOL_TYPE PoolType,
|
||||||
IN ULONG Threshold)
|
IN ULONG Threshold)
|
||||||
{
|
{
|
||||||
PPOOL_DESCRIPTOR Descriptor;
|
PPOOL_DESCRIPTOR Descriptor;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check what kind of pool this is
|
// Check what kind of pool this is
|
||||||
//
|
//
|
||||||
|
@ -375,7 +374,7 @@ InitializePool(IN POOL_TYPE PoolType,
|
||||||
-1,
|
-1,
|
||||||
-1);
|
-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup the vector and guarded mutex for paged pool
|
// Setup the vector and guarded mutex for paged pool
|
||||||
//
|
//
|
||||||
|
@ -461,14 +460,14 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
ASSERT(Tag != 0);
|
ASSERT(Tag != 0);
|
||||||
ASSERT(Tag != ' GIB');
|
ASSERT(Tag != ' GIB');
|
||||||
ASSERT(NumberOfBytes != 0);
|
ASSERT(NumberOfBytes != 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the pool type and its corresponding vector for this request
|
// Get the pool type and its corresponding vector for this request
|
||||||
//
|
//
|
||||||
PoolType = PoolType & BASE_POOL_TYPE_MASK;
|
PoolType = PoolType & BASE_POOL_TYPE_MASK;
|
||||||
PoolDesc = PoolVector[PoolType];
|
PoolDesc = PoolVector[PoolType];
|
||||||
ASSERT(PoolDesc != NULL);
|
ASSERT(PoolDesc != NULL);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is a big page allocation
|
// Check if this is a big page allocation
|
||||||
//
|
//
|
||||||
|
@ -479,13 +478,13 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
//
|
//
|
||||||
return MiAllocatePoolPages(PoolType, NumberOfBytes);
|
return MiAllocatePoolPages(PoolType, NumberOfBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Should never request 0 bytes from the pool, but since so many drivers do
|
// Should never request 0 bytes from the pool, but since so many drivers do
|
||||||
// it, we'll just assume they want 1 byte, based on NT's similar behavior
|
// it, we'll just assume they want 1 byte, based on NT's similar behavior
|
||||||
//
|
//
|
||||||
if (!NumberOfBytes) NumberOfBytes = 1;
|
if (!NumberOfBytes) NumberOfBytes = 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// A pool allocation is defined by its data, a linked list to connect it to
|
// A pool allocation is defined by its data, a linked list to connect it to
|
||||||
// the free list (if necessary), and a pool header to store accounting info.
|
// the free list (if necessary), and a pool header to store accounting info.
|
||||||
|
@ -514,7 +513,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// Acquire the pool lock now
|
// Acquire the pool lock now
|
||||||
//
|
//
|
||||||
OldIrql = ExLockPool(PoolDesc);
|
OldIrql = ExLockPool(PoolDesc);
|
||||||
|
|
||||||
//
|
//
|
||||||
// And make sure the list still has entries
|
// And make sure the list still has entries
|
||||||
//
|
//
|
||||||
|
@ -530,7 +529,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
ListHead++;
|
ListHead++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Remove a free entry from the list
|
// Remove a free entry from the list
|
||||||
// Note that due to the way we insert free blocks into multiple lists
|
// Note that due to the way we insert free blocks into multiple lists
|
||||||
|
@ -543,7 +542,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
ExpCheckPoolBlocks(Entry);
|
ExpCheckPoolBlocks(Entry);
|
||||||
ASSERT(Entry->BlockSize >= i);
|
ASSERT(Entry->BlockSize >= i);
|
||||||
ASSERT(Entry->PoolType == 0);
|
ASSERT(Entry->PoolType == 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this block is larger that what we need. The block could
|
// Check if this block is larger that what we need. The block could
|
||||||
// not possibly be smaller, due to the reason explained above (and
|
// not possibly be smaller, due to the reason explained above (and
|
||||||
|
@ -563,12 +562,12 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
//
|
//
|
||||||
FragmentEntry = POOL_BLOCK(Entry, i);
|
FragmentEntry = POOL_BLOCK(Entry, i);
|
||||||
FragmentEntry->BlockSize = Entry->BlockSize - i;
|
FragmentEntry->BlockSize = Entry->BlockSize - i;
|
||||||
|
|
||||||
//
|
//
|
||||||
// And make it point back to us
|
// And make it point back to us
|
||||||
//
|
//
|
||||||
FragmentEntry->PreviousSize = i;
|
FragmentEntry->PreviousSize = i;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now get the block that follows the new fragment and check
|
// Now get the block that follows the new fragment and check
|
||||||
// if it's still on the same page as us (and not at the end)
|
// if it's still on the same page as us (and not at the end)
|
||||||
|
@ -581,7 +580,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// fragment block
|
// fragment block
|
||||||
//
|
//
|
||||||
NextEntry->PreviousSize = FragmentEntry->BlockSize;
|
NextEntry->PreviousSize = FragmentEntry->BlockSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -590,13 +589,13 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// so we'll make this entry the fragment instead
|
// so we'll make this entry the fragment instead
|
||||||
//
|
//
|
||||||
FragmentEntry = Entry;
|
FragmentEntry = Entry;
|
||||||
|
|
||||||
//
|
//
|
||||||
// And then we'll remove from it the actual size required.
|
// And then we'll remove from it the actual size required.
|
||||||
// Now the entry is a leftover free fragment
|
// Now the entry is a leftover free fragment
|
||||||
//
|
//
|
||||||
Entry->BlockSize -= i;
|
Entry->BlockSize -= i;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now let's go to the next entry after the fragment (which
|
// Now let's go to the next entry after the fragment (which
|
||||||
// used to point to our original free entry) and make it
|
// used to point to our original free entry) and make it
|
||||||
|
@ -607,7 +606,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
//
|
//
|
||||||
Entry = POOL_NEXT_BLOCK(Entry);
|
Entry = POOL_NEXT_BLOCK(Entry);
|
||||||
Entry->PreviousSize = FragmentEntry->BlockSize;
|
Entry->PreviousSize = FragmentEntry->BlockSize;
|
||||||
|
|
||||||
//
|
//
|
||||||
// And now let's go to the entry after that one and check if
|
// And now let's go to the entry after that one and check if
|
||||||
// it's still on the same page, and not at the end
|
// it's still on the same page, and not at the end
|
||||||
|
@ -621,12 +620,12 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
NextEntry->PreviousSize = i;
|
NextEntry->PreviousSize = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now our (allocation) entry is the right size
|
// Now our (allocation) entry is the right size
|
||||||
//
|
//
|
||||||
Entry->BlockSize = i;
|
Entry->BlockSize = i;
|
||||||
|
|
||||||
//
|
//
|
||||||
// And the next entry is now the free fragment which contains
|
// And the next entry is now the free fragment which contains
|
||||||
// the remaining difference between how big the original entry
|
// the remaining difference between how big the original entry
|
||||||
|
@ -634,10 +633,10 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
//
|
//
|
||||||
FragmentEntry->PoolType = 0;
|
FragmentEntry->PoolType = 0;
|
||||||
BlockSize = FragmentEntry->BlockSize;
|
BlockSize = FragmentEntry->BlockSize;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now check if enough free bytes remained for us to have a
|
// Now check if enough free bytes remained for us to have a
|
||||||
// "full" entry, which contains enough bytes for a linked list
|
// "full" entry, which contains enough bytes for a linked list
|
||||||
// and thus can be used for allocations (up to 8 bytes...)
|
// and thus can be used for allocations (up to 8 bytes...)
|
||||||
//
|
//
|
||||||
ExpCheckPoolLinks(&PoolDesc->ListHeads[BlockSize - 1]);
|
ExpCheckPoolLinks(&PoolDesc->ListHeads[BlockSize - 1]);
|
||||||
|
@ -651,7 +650,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
ExpCheckPoolLinks(POOL_FREE_BLOCK(FragmentEntry));
|
ExpCheckPoolLinks(POOL_FREE_BLOCK(FragmentEntry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// We have found an entry for this allocation, so set the pool type
|
// We have found an entry for this allocation, so set the pool type
|
||||||
// and release the lock since we're done
|
// and release the lock since we're done
|
||||||
|
@ -669,7 +668,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
return POOL_FREE_BLOCK(Entry);
|
return POOL_FREE_BLOCK(Entry);
|
||||||
}
|
}
|
||||||
} while (++ListHead != &PoolDesc->ListHeads[POOL_LISTS_PER_PAGE]);
|
} while (++ListHead != &PoolDesc->ListHeads[POOL_LISTS_PER_PAGE]);
|
||||||
|
|
||||||
//
|
//
|
||||||
// There were no free entries left, so we have to allocate a new fresh page
|
// There were no free entries left, so we have to allocate a new fresh page
|
||||||
//
|
//
|
||||||
|
@ -678,7 +677,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
Entry->Ulong1 = 0;
|
Entry->Ulong1 = 0;
|
||||||
Entry->BlockSize = i;
|
Entry->BlockSize = i;
|
||||||
Entry->PoolType = PoolType + 1;
|
Entry->PoolType = PoolType + 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// This page will have two entries -- one for the allocation (which we just
|
// This page will have two entries -- one for the allocation (which we just
|
||||||
// created above), and one for the remaining free bytes, which we're about
|
// created above), and one for the remaining free bytes, which we're about
|
||||||
|
@ -690,7 +689,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
FragmentEntry->Ulong1 = 0;
|
FragmentEntry->Ulong1 = 0;
|
||||||
FragmentEntry->BlockSize = BlockSize;
|
FragmentEntry->BlockSize = BlockSize;
|
||||||
FragmentEntry->PreviousSize = i;
|
FragmentEntry->PreviousSize = i;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now check if enough free bytes remained for us to have a "full" entry,
|
// Now check if enough free bytes remained for us to have a "full" entry,
|
||||||
// which contains enough bytes for a linked list and thus can be used for
|
// which contains enough bytes for a linked list and thus can be used for
|
||||||
|
@ -710,7 +709,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
ExpInsertPoolTailList(&PoolDesc->ListHeads[BlockSize - 1],
|
ExpInsertPoolTailList(&PoolDesc->ListHeads[BlockSize - 1],
|
||||||
POOL_FREE_BLOCK(FragmentEntry));
|
POOL_FREE_BLOCK(FragmentEntry));
|
||||||
ExpCheckPoolLinks(POOL_FREE_BLOCK(FragmentEntry));
|
ExpCheckPoolLinks(POOL_FREE_BLOCK(FragmentEntry));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the pool lock
|
// Release the pool lock
|
||||||
//
|
//
|
||||||
|
@ -763,14 +762,14 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
MiFreePoolPages(P);
|
MiFreePoolPages(P);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the entry for this pool allocation
|
// Get the entry for this pool allocation
|
||||||
// The pointer math here may look wrong or confusing, but it is quite right
|
// The pointer math here may look wrong or confusing, but it is quite right
|
||||||
//
|
//
|
||||||
Entry = P;
|
Entry = P;
|
||||||
Entry--;
|
Entry--;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the size of the entry, and it's pool type, then load the descriptor
|
// Get the size of the entry, and it's pool type, then load the descriptor
|
||||||
// for this pool type
|
// for this pool type
|
||||||
|
@ -804,7 +803,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
// The next block is free, so we'll do a combine
|
// The next block is free, so we'll do a combine
|
||||||
//
|
//
|
||||||
Combined = TRUE;
|
Combined = TRUE;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make sure there's actual data in the block -- anything smaller
|
// Make sure there's actual data in the block -- anything smaller
|
||||||
// than this means we only have the header, so there's no linked list
|
// than this means we only have the header, so there's no linked list
|
||||||
|
@ -821,7 +820,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
ExpCheckPoolLinks(ExpDecodePoolLink((POOL_FREE_BLOCK(NextEntry))->Flink));
|
ExpCheckPoolLinks(ExpDecodePoolLink((POOL_FREE_BLOCK(NextEntry))->Flink));
|
||||||
ExpCheckPoolLinks(ExpDecodePoolLink((POOL_FREE_BLOCK(NextEntry))->Blink));
|
ExpCheckPoolLinks(ExpDecodePoolLink((POOL_FREE_BLOCK(NextEntry))->Blink));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Our entry is now combined with the next entry
|
// Our entry is now combined with the next entry
|
||||||
//
|
//
|
||||||
|
@ -844,7 +843,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
// It is, so we can do a combine
|
// It is, so we can do a combine
|
||||||
//
|
//
|
||||||
Combined = TRUE;
|
Combined = TRUE;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make sure there's actual data in the block -- anything smaller
|
// Make sure there's actual data in the block -- anything smaller
|
||||||
// than this means we only have the header so there's no linked list
|
// than this means we only have the header so there's no linked list
|
||||||
|
@ -861,20 +860,20 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
ExpCheckPoolLinks(ExpDecodePoolLink((POOL_FREE_BLOCK(NextEntry))->Flink));
|
ExpCheckPoolLinks(ExpDecodePoolLink((POOL_FREE_BLOCK(NextEntry))->Flink));
|
||||||
ExpCheckPoolLinks(ExpDecodePoolLink((POOL_FREE_BLOCK(NextEntry))->Blink));
|
ExpCheckPoolLinks(ExpDecodePoolLink((POOL_FREE_BLOCK(NextEntry))->Blink));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Combine our original block (which might've already been combined
|
// Combine our original block (which might've already been combined
|
||||||
// with the next block), into the previous block
|
// with the next block), into the previous block
|
||||||
//
|
//
|
||||||
NextEntry->BlockSize = NextEntry->BlockSize + Entry->BlockSize;
|
NextEntry->BlockSize = NextEntry->BlockSize + Entry->BlockSize;
|
||||||
|
|
||||||
//
|
//
|
||||||
// And now we'll work with the previous block instead
|
// And now we'll work with the previous block instead
|
||||||
//
|
//
|
||||||
Entry = NextEntry;
|
Entry = NextEntry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// By now, it may have been possible for our combined blocks to actually
|
// By now, it may have been possible for our combined blocks to actually
|
||||||
// have made up a full page (if there were only 2-3 allocations on the
|
// have made up a full page (if there were only 2-3 allocations on the
|
||||||
|
@ -897,7 +896,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
Entry->PoolType = 0;
|
Entry->PoolType = 0;
|
||||||
BlockSize = Entry->BlockSize;
|
BlockSize = Entry->BlockSize;
|
||||||
ASSERT(BlockSize != 1);
|
ASSERT(BlockSize != 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we actually did combine it with anyone
|
// Check if we actually did combine it with anyone
|
||||||
//
|
//
|
||||||
|
@ -908,14 +907,14 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
// the one after the original, depending if we combined with the previous)
|
// the one after the original, depending if we combined with the previous)
|
||||||
//
|
//
|
||||||
NextEntry = POOL_NEXT_BLOCK(Entry);
|
NextEntry = POOL_NEXT_BLOCK(Entry);
|
||||||
|
|
||||||
//
|
//
|
||||||
// As long as the next block isn't on a page boundary, have it point
|
// As long as the next block isn't on a page boundary, have it point
|
||||||
// back to us
|
// back to us
|
||||||
//
|
//
|
||||||
if (PAGE_ALIGN(NextEntry) != NextEntry) NextEntry->PreviousSize = BlockSize;
|
if (PAGE_ALIGN(NextEntry) != NextEntry) NextEntry->PreviousSize = BlockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Insert this new free block, and release the pool lock
|
// Insert this new free block, and release the pool lock
|
||||||
//
|
//
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::HYPERMAP"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -125,7 +124,7 @@ MiMapPagesToZeroInHyperSpace(IN PMMPFN Pfn1,
|
||||||
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||||
ASSERT(NumberOfPages != 0);
|
ASSERT(NumberOfPages != 0);
|
||||||
ASSERT(NumberOfPages <= (MI_ZERO_PTES - 1));
|
ASSERT(NumberOfPages <= (MI_ZERO_PTES - 1));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Pick the first zeroing PTE
|
// Pick the first zeroing PTE
|
||||||
//
|
//
|
||||||
|
@ -144,39 +143,39 @@ MiMapPagesToZeroInHyperSpace(IN PMMPFN Pfn1,
|
||||||
PointerPte->u.Hard.PageFrameNumber = Offset;
|
PointerPte->u.Hard.PageFrameNumber = Offset;
|
||||||
KeFlushProcessTb();
|
KeFlushProcessTb();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Prepare the next PTE
|
// Prepare the next PTE
|
||||||
//
|
//
|
||||||
PointerPte->u.Hard.PageFrameNumber = Offset - NumberOfPages;
|
PointerPte->u.Hard.PageFrameNumber = Offset - NumberOfPages;
|
||||||
|
|
||||||
/* Choose the correct PTE to use, and which template */
|
/* Choose the correct PTE to use, and which template */
|
||||||
PointerPte += (Offset + 1);
|
PointerPte += (Offset + 1);
|
||||||
TempPte = ValidKernelPte;
|
TempPte = ValidKernelPte;
|
||||||
MI_MAKE_LOCAL_PAGE(&TempPte); // Hyperspace is local!
|
MI_MAKE_LOCAL_PAGE(&TempPte); // Hyperspace is local!
|
||||||
|
|
||||||
/* Make sure the list isn't empty and loop it */
|
/* Make sure the list isn't empty and loop it */
|
||||||
ASSERT(Pfn1 != (PVOID)LIST_HEAD);
|
ASSERT(Pfn1 != (PVOID)LIST_HEAD);
|
||||||
while (Pfn1 != (PVOID)LIST_HEAD)
|
while (Pfn1 != (PVOID)LIST_HEAD)
|
||||||
{
|
{
|
||||||
/* Get the page index for this PFN */
|
/* Get the page index for this PFN */
|
||||||
PageFrameIndex = MiGetPfnEntryIndex(Pfn1);
|
PageFrameIndex = MiGetPfnEntryIndex(Pfn1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Write the PFN
|
// Write the PFN
|
||||||
//
|
//
|
||||||
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set the correct PTE to write to, and set its new value
|
// Set the correct PTE to write to, and set its new value
|
||||||
//
|
//
|
||||||
PointerPte--;
|
PointerPte--;
|
||||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
|
||||||
/* Move to the next PFN */
|
/* Move to the next PFN */
|
||||||
Pfn1 = (PMMPFN)Pfn1->u1.Flink;
|
Pfn1 = (PMMPFN)Pfn1->u1.Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return the address
|
// Return the address
|
||||||
//
|
//
|
||||||
|
@ -189,14 +188,14 @@ MiUnmapPagesInZeroSpace(IN PVOID VirtualAddress,
|
||||||
IN PFN_NUMBER NumberOfPages)
|
IN PFN_NUMBER NumberOfPages)
|
||||||
{
|
{
|
||||||
PMMPTE PointerPte;
|
PMMPTE PointerPte;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
//
|
//
|
||||||
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||||
ASSERT (NumberOfPages != 0);
|
ASSERT (NumberOfPages != 0);
|
||||||
ASSERT (NumberOfPages <= (MI_ZERO_PTES - 1));
|
ASSERT (NumberOfPages <= (MI_ZERO_PTES - 1));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the first PTE for the mapped zero VA
|
// Get the first PTE for the mapped zero VA
|
||||||
//
|
//
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::INIT:X86"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../../ARM3/miarm.h"
|
#include "../../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -28,7 +27,7 @@ MMPTE DemandZeroPte = {.u.Long = (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BI
|
||||||
|
|
||||||
/* Template PTE for prototype page */
|
/* Template PTE for prototype page */
|
||||||
MMPTE PrototypePte = {.u.Long = (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS) | PTE_PROTOTYPE | (MI_PTE_LOOKUP_NEEDED << PAGE_SHIFT)};
|
MMPTE PrototypePte = {.u.Long = (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS) | PTE_PROTOTYPE | (MI_PTE_LOOKUP_NEEDED << PAGE_SHIFT)};
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -37,7 +36,7 @@ INIT_FUNCTION
|
||||||
MiComputeNonPagedPoolVa(IN ULONG FreePages)
|
MiComputeNonPagedPoolVa(IN ULONG FreePages)
|
||||||
{
|
{
|
||||||
IN PFN_NUMBER PoolPages;
|
IN PFN_NUMBER PoolPages;
|
||||||
|
|
||||||
/* Check if this is a machine with less than 256MB of RAM, and no overide */
|
/* Check if this is a machine with less than 256MB of RAM, and no overide */
|
||||||
if ((MmNumberOfPhysicalPages <= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING) &&
|
if ((MmNumberOfPhysicalPages <= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING) &&
|
||||||
!(MmSizeOfNonPagedPoolInBytes))
|
!(MmSizeOfNonPagedPoolInBytes))
|
||||||
|
@ -45,17 +44,17 @@ MiComputeNonPagedPoolVa(IN ULONG FreePages)
|
||||||
/* Force the non paged pool to be 2MB so we can reduce RAM usage */
|
/* Force the non paged pool to be 2MB so we can reduce RAM usage */
|
||||||
MmSizeOfNonPagedPoolInBytes = 2 * _1MB;
|
MmSizeOfNonPagedPoolInBytes = 2 * _1MB;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hyperspace ends here */
|
/* Hyperspace ends here */
|
||||||
MmHyperSpaceEnd = (PVOID)((ULONG_PTR)MmSystemCacheWorkingSetList - 1);
|
MmHyperSpaceEnd = (PVOID)((ULONG_PTR)MmSystemCacheWorkingSetList - 1);
|
||||||
|
|
||||||
/* Check if the user gave a ridicuously large nonpaged pool RAM size */
|
/* Check if the user gave a ridicuously large nonpaged pool RAM size */
|
||||||
if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) > (FreePages * 7 / 8))
|
if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) > (FreePages * 7 / 8))
|
||||||
{
|
{
|
||||||
/* More than 7/8ths of RAM was dedicated to nonpaged pool, ignore! */
|
/* More than 7/8ths of RAM was dedicated to nonpaged pool, ignore! */
|
||||||
MmSizeOfNonPagedPoolInBytes = 0;
|
MmSizeOfNonPagedPoolInBytes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if no registry setting was set, or if the setting was too low */
|
/* Check if no registry setting was set, or if the setting was too low */
|
||||||
if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize)
|
if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize)
|
||||||
{
|
{
|
||||||
|
@ -63,30 +62,30 @@ MiComputeNonPagedPoolVa(IN ULONG FreePages)
|
||||||
MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize;
|
MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize;
|
||||||
MmSizeOfNonPagedPoolInBytes += (FreePages - 1024) / 256 * MmMinAdditionNonPagedPoolPerMb;
|
MmSizeOfNonPagedPoolInBytes += (FreePages - 1024) / 256 * MmMinAdditionNonPagedPoolPerMb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the registy setting or our dynamic calculation was too high */
|
/* Check if the registy setting or our dynamic calculation was too high */
|
||||||
if (MmSizeOfNonPagedPoolInBytes > MI_MAX_INIT_NONPAGED_POOL_SIZE)
|
if (MmSizeOfNonPagedPoolInBytes > MI_MAX_INIT_NONPAGED_POOL_SIZE)
|
||||||
{
|
{
|
||||||
/* Set it to the maximum */
|
/* Set it to the maximum */
|
||||||
MmSizeOfNonPagedPoolInBytes = MI_MAX_INIT_NONPAGED_POOL_SIZE;
|
MmSizeOfNonPagedPoolInBytes = MI_MAX_INIT_NONPAGED_POOL_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if a percentage cap was set through the registry */
|
/* Check if a percentage cap was set through the registry */
|
||||||
if (MmMaximumNonPagedPoolPercent) UNIMPLEMENTED;
|
if (MmMaximumNonPagedPoolPercent) UNIMPLEMENTED;
|
||||||
|
|
||||||
/* Page-align the nonpaged pool size */
|
/* Page-align the nonpaged pool size */
|
||||||
MmSizeOfNonPagedPoolInBytes &= ~(PAGE_SIZE - 1);
|
MmSizeOfNonPagedPoolInBytes &= ~(PAGE_SIZE - 1);
|
||||||
|
|
||||||
/* Now, check if there was a registry size for the maximum size */
|
/* Now, check if there was a registry size for the maximum size */
|
||||||
if (!MmMaximumNonPagedPoolInBytes)
|
if (!MmMaximumNonPagedPoolInBytes)
|
||||||
{
|
{
|
||||||
/* Start with the default (1MB) */
|
/* Start with the default (1MB) */
|
||||||
MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool;
|
MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool;
|
||||||
|
|
||||||
/* Add space for PFN database */
|
/* Add space for PFN database */
|
||||||
MmMaximumNonPagedPoolInBytes += (ULONG)
|
MmMaximumNonPagedPoolInBytes += (ULONG)
|
||||||
PAGE_ALIGN((MmHighestPhysicalPage + 1) * sizeof(MMPFN));
|
PAGE_ALIGN((MmHighestPhysicalPage + 1) * sizeof(MMPFN));
|
||||||
|
|
||||||
/* Check if the machine has more than 512MB of free RAM */
|
/* Check if the machine has more than 512MB of free RAM */
|
||||||
if (FreePages >= 0x1F000)
|
if (FreePages >= 0x1F000)
|
||||||
{
|
{
|
||||||
|
@ -106,7 +105,7 @@ MiComputeNonPagedPoolVa(IN ULONG FreePages)
|
||||||
MmMaxAdditionNonPagedPoolPerMb;
|
MmMaxAdditionNonPagedPoolPerMb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure there's at least 16 pages + the PFN available for expansion */
|
/* Make sure there's at least 16 pages + the PFN available for expansion */
|
||||||
PoolPages = MmSizeOfNonPagedPoolInBytes + (PAGE_SIZE * 16) +
|
PoolPages = MmSizeOfNonPagedPoolInBytes + (PAGE_SIZE * 16) +
|
||||||
((ULONG)PAGE_ALIGN(MmHighestPhysicalPage + 1) * sizeof(MMPFN));
|
((ULONG)PAGE_ALIGN(MmHighestPhysicalPage + 1) * sizeof(MMPFN));
|
||||||
|
@ -115,17 +114,17 @@ MiComputeNonPagedPoolVa(IN ULONG FreePages)
|
||||||
/* The maximum should be at least high enough to cover all the above */
|
/* The maximum should be at least high enough to cover all the above */
|
||||||
MmMaximumNonPagedPoolInBytes = PoolPages;
|
MmMaximumNonPagedPoolInBytes = PoolPages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Systems with 2GB of kernel address space get double the size */
|
/* Systems with 2GB of kernel address space get double the size */
|
||||||
PoolPages = MI_MAX_NONPAGED_POOL_SIZE * 2;
|
PoolPages = MI_MAX_NONPAGED_POOL_SIZE * 2;
|
||||||
|
|
||||||
/* On the other hand, make sure that PFN + nonpaged pool doesn't get too big */
|
/* On the other hand, make sure that PFN + nonpaged pool doesn't get too big */
|
||||||
if (MmMaximumNonPagedPoolInBytes > PoolPages)
|
if (MmMaximumNonPagedPoolInBytes > PoolPages)
|
||||||
{
|
{
|
||||||
/* Trim it down to the maximum architectural limit (256MB) */
|
/* Trim it down to the maximum architectural limit (256MB) */
|
||||||
MmMaximumNonPagedPoolInBytes = PoolPages;
|
MmMaximumNonPagedPoolInBytes = PoolPages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if this is a system with > 128MB of non paged pool */
|
/* Check if this is a system with > 128MB of non paged pool */
|
||||||
if (MmMaximumNonPagedPoolInBytes > MI_MAX_NONPAGED_POOL_SIZE)
|
if (MmMaximumNonPagedPoolInBytes > MI_MAX_NONPAGED_POOL_SIZE)
|
||||||
{
|
{
|
||||||
|
@ -134,7 +133,7 @@ MiComputeNonPagedPoolVa(IN ULONG FreePages)
|
||||||
MI_MAX_NONPAGED_POOL_SIZE))
|
MI_MAX_NONPAGED_POOL_SIZE))
|
||||||
{
|
{
|
||||||
/* FIXME: Should check if the initial pool can be expanded */
|
/* FIXME: Should check if the initial pool can be expanded */
|
||||||
|
|
||||||
/* Assume no expansion possible, check ift he maximum is too large */
|
/* Assume no expansion possible, check ift he maximum is too large */
|
||||||
if (MmMaximumNonPagedPoolInBytes > (MmSizeOfNonPagedPoolInBytes +
|
if (MmMaximumNonPagedPoolInBytes > (MmSizeOfNonPagedPoolInBytes +
|
||||||
MI_MAX_NONPAGED_POOL_SIZE))
|
MI_MAX_NONPAGED_POOL_SIZE))
|
||||||
|
@ -142,7 +141,7 @@ MiComputeNonPagedPoolVa(IN ULONG FreePages)
|
||||||
/* Set it to the initial value plus the boost */
|
/* Set it to the initial value plus the boost */
|
||||||
MmMaximumNonPagedPoolInBytes = MmSizeOfNonPagedPoolInBytes +
|
MmMaximumNonPagedPoolInBytes = MmSizeOfNonPagedPoolInBytes +
|
||||||
MI_MAX_NONPAGED_POOL_SIZE;
|
MI_MAX_NONPAGED_POOL_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,7 +161,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
|
|
||||||
/* Check for kernel stack size that's too big */
|
/* Check for kernel stack size that's too big */
|
||||||
if (MmLargeStackSize > (KERNEL_LARGE_STACK_SIZE / _1KB))
|
if (MmLargeStackSize > (KERNEL_LARGE_STACK_SIZE / _1KB))
|
||||||
{
|
{
|
||||||
|
@ -173,18 +172,18 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
{
|
{
|
||||||
/* Take the registry setting, and convert it into bytes */
|
/* Take the registry setting, and convert it into bytes */
|
||||||
MmLargeStackSize *= _1KB;
|
MmLargeStackSize *= _1KB;
|
||||||
|
|
||||||
/* Now align it to a page boundary */
|
/* Now align it to a page boundary */
|
||||||
MmLargeStackSize = PAGE_ROUND_UP(MmLargeStackSize);
|
MmLargeStackSize = PAGE_ROUND_UP(MmLargeStackSize);
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
ASSERT(MmLargeStackSize <= KERNEL_LARGE_STACK_SIZE);
|
ASSERT(MmLargeStackSize <= KERNEL_LARGE_STACK_SIZE);
|
||||||
ASSERT((MmLargeStackSize & (PAGE_SIZE - 1)) == 0);
|
ASSERT((MmLargeStackSize & (PAGE_SIZE - 1)) == 0);
|
||||||
|
|
||||||
/* Make sure it's not too low */
|
/* Make sure it's not too low */
|
||||||
if (MmLargeStackSize < KERNEL_STACK_SIZE) MmLargeStackSize = KERNEL_STACK_SIZE;
|
if (MmLargeStackSize < KERNEL_STACK_SIZE) MmLargeStackSize = KERNEL_STACK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for global bit */
|
/* Check for global bit */
|
||||||
#if 0
|
#if 0
|
||||||
if (KeFeatureBits & KF_GLOBAL_PAGE)
|
if (KeFeatureBits & KF_GLOBAL_PAGE)
|
||||||
|
@ -197,21 +196,21 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
/* Now templates are ready */
|
/* Now templates are ready */
|
||||||
TempPte = ValidKernelPte;
|
TempPte = ValidKernelPte;
|
||||||
TempPde = ValidKernelPde;
|
TempPde = ValidKernelPde;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set CR3 for the system process
|
// Set CR3 for the system process
|
||||||
//
|
//
|
||||||
PointerPte = MiAddressToPde(PDE_BASE);
|
PointerPte = MiAddressToPde(PDE_BASE);
|
||||||
PageFrameIndex = PFN_FROM_PTE(PointerPte) << PAGE_SHIFT;
|
PageFrameIndex = PFN_FROM_PTE(PointerPte) << PAGE_SHIFT;
|
||||||
PsGetCurrentProcess()->Pcb.DirectoryTableBase[0] = PageFrameIndex;
|
PsGetCurrentProcess()->Pcb.DirectoryTableBase[0] = PageFrameIndex;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Blow away user-mode
|
// Blow away user-mode
|
||||||
//
|
//
|
||||||
StartPde = MiAddressToPde(0);
|
StartPde = MiAddressToPde(0);
|
||||||
EndPde = MiAddressToPde(KSEG0_BASE);
|
EndPde = MiAddressToPde(KSEG0_BASE);
|
||||||
RtlZeroMemory(StartPde, (EndPde - StartPde) * sizeof(MMPTE));
|
RtlZeroMemory(StartPde, (EndPde - StartPde) * sizeof(MMPTE));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop the memory descriptors
|
// Loop the memory descriptors
|
||||||
//
|
//
|
||||||
|
@ -224,7 +223,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
MdBlock = CONTAINING_RECORD(NextEntry,
|
MdBlock = CONTAINING_RECORD(NextEntry,
|
||||||
MEMORY_ALLOCATION_DESCRIPTOR,
|
MEMORY_ALLOCATION_DESCRIPTOR,
|
||||||
ListEntry);
|
ListEntry);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Skip invisible memory
|
// Skip invisible memory
|
||||||
//
|
//
|
||||||
|
@ -243,7 +242,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
//
|
//
|
||||||
MmNumberOfPhysicalPages += MdBlock->PageCount;
|
MmNumberOfPhysicalPages += MdBlock->PageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is the new lowest page
|
// Check if this is the new lowest page
|
||||||
//
|
//
|
||||||
|
@ -254,7 +253,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
//
|
//
|
||||||
MmLowestPhysicalPage = MdBlock->BasePage;
|
MmLowestPhysicalPage = MdBlock->BasePage;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is the new highest page
|
// Check if this is the new highest page
|
||||||
//
|
//
|
||||||
|
@ -266,7 +265,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
//
|
//
|
||||||
MmHighestPhysicalPage = PageFrameIndex - 1;
|
MmHighestPhysicalPage = PageFrameIndex - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is free memory
|
// Check if this is free memory
|
||||||
//
|
//
|
||||||
|
@ -285,32 +284,32 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
//
|
//
|
||||||
MxFreeDescriptor = MdBlock;
|
MxFreeDescriptor = MdBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// More free pages
|
// More free pages
|
||||||
//
|
//
|
||||||
FreePages += MdBlock->PageCount;
|
FreePages += MdBlock->PageCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Keep going
|
// Keep going
|
||||||
//
|
//
|
||||||
NextEntry = MdBlock->ListEntry.Flink;
|
NextEntry = MdBlock->ListEntry.Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Save original values of the free descriptor, since it'll be
|
// Save original values of the free descriptor, since it'll be
|
||||||
// altered by early allocations
|
// altered by early allocations
|
||||||
//
|
//
|
||||||
MxOldFreeDescriptor = *MxFreeDescriptor;
|
MxOldFreeDescriptor = *MxFreeDescriptor;
|
||||||
|
|
||||||
/* Compute non paged pool limits and size */
|
/* Compute non paged pool limits and size */
|
||||||
MiComputeNonPagedPoolVa(FreePages);
|
MiComputeNonPagedPoolVa(FreePages);
|
||||||
|
|
||||||
/* Compute color information (L2 cache-separated paging lists) */
|
/* Compute color information (L2 cache-separated paging lists) */
|
||||||
MiComputeColorInformation();
|
MiComputeColorInformation();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Calculate the number of bytes for the PFN database
|
// Calculate the number of bytes for the PFN database
|
||||||
// then add the color tables and convert to pages
|
// then add the color tables and convert to pages
|
||||||
|
@ -318,7 +317,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
MxPfnAllocation = (MmHighestPhysicalPage + 1) * sizeof(MMPFN);
|
MxPfnAllocation = (MmHighestPhysicalPage + 1) * sizeof(MMPFN);
|
||||||
MxPfnAllocation += (MmSecondaryColors * sizeof(MMCOLOR_TABLES) * 2);
|
MxPfnAllocation += (MmSecondaryColors * sizeof(MMCOLOR_TABLES) * 2);
|
||||||
MxPfnAllocation >>= PAGE_SHIFT;
|
MxPfnAllocation >>= PAGE_SHIFT;
|
||||||
|
|
||||||
//
|
//
|
||||||
// We have to add one to the count here, because in the process of
|
// We have to add one to the count here, because in the process of
|
||||||
// shifting down to the page size, we actually ended up getting the
|
// shifting down to the page size, we actually ended up getting the
|
||||||
|
@ -328,7 +327,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
// 0x60000 bytes.
|
// 0x60000 bytes.
|
||||||
//
|
//
|
||||||
MxPfnAllocation++;
|
MxPfnAllocation++;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now calculate the nonpaged pool expansion VA region
|
// Now calculate the nonpaged pool expansion VA region
|
||||||
//
|
//
|
||||||
|
@ -339,7 +338,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
NonPagedPoolExpansionVa = MmNonPagedPoolStart;
|
NonPagedPoolExpansionVa = MmNonPagedPoolStart;
|
||||||
DPRINT("NP Pool has been tuned to: %d bytes and %d bytes\n",
|
DPRINT("NP Pool has been tuned to: %d bytes and %d bytes\n",
|
||||||
MmSizeOfNonPagedPoolInBytes, MmMaximumNonPagedPoolInBytes);
|
MmSizeOfNonPagedPoolInBytes, MmMaximumNonPagedPoolInBytes);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now calculate the nonpaged system VA region, which includes the
|
// Now calculate the nonpaged system VA region, which includes the
|
||||||
// nonpaged pool expansion (above) and the system PTEs. Note that it is
|
// nonpaged pool expansion (above) and the system PTEs. Note that it is
|
||||||
|
@ -349,7 +348,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
(MmNumberOfSystemPtes + 1) * PAGE_SIZE);
|
(MmNumberOfSystemPtes + 1) * PAGE_SIZE);
|
||||||
MmNonPagedSystemStart = (PVOID)((ULONG_PTR)MmNonPagedSystemStart &
|
MmNonPagedSystemStart = (PVOID)((ULONG_PTR)MmNonPagedSystemStart &
|
||||||
~(PDE_MAPPED_VA - 1));
|
~(PDE_MAPPED_VA - 1));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Don't let it go below the minimum
|
// Don't let it go below the minimum
|
||||||
//
|
//
|
||||||
|
@ -359,7 +358,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
// This is a hard-coded limit in the Windows NT address space
|
// This is a hard-coded limit in the Windows NT address space
|
||||||
//
|
//
|
||||||
MmNonPagedSystemStart = (PVOID)0xEB000000;
|
MmNonPagedSystemStart = (PVOID)0xEB000000;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reduce the amount of system PTEs to reach this point
|
// Reduce the amount of system PTEs to reach this point
|
||||||
//
|
//
|
||||||
|
@ -369,7 +368,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
MmNumberOfSystemPtes--;
|
MmNumberOfSystemPtes--;
|
||||||
ASSERT(MmNumberOfSystemPtes > 1000);
|
ASSERT(MmNumberOfSystemPtes > 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we are in a situation where the size of the paged pool
|
// Check if we are in a situation where the size of the paged pool
|
||||||
// is so large that it overflows into nonpaged pool
|
// is so large that it overflows into nonpaged pool
|
||||||
|
@ -382,7 +381,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
//
|
//
|
||||||
DPRINT1("Paged pool is too big!\n");
|
DPRINT1("Paged pool is too big!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Normally, the PFN database should start after the loader images.
|
// Normally, the PFN database should start after the loader images.
|
||||||
// This is already the case in ReactOS, but for now we want to co-exist
|
// This is already the case in ReactOS, but for now we want to co-exist
|
||||||
|
@ -391,7 +390,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
//
|
//
|
||||||
MmPfnDatabase = (PVOID)0xB0000000;
|
MmPfnDatabase = (PVOID)0xB0000000;
|
||||||
ASSERT(((ULONG_PTR)MmPfnDatabase & (PDE_MAPPED_VA - 1)) == 0);
|
ASSERT(((ULONG_PTR)MmPfnDatabase & (PDE_MAPPED_VA - 1)) == 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Non paged pool comes after the PFN database
|
// Non paged pool comes after the PFN database
|
||||||
//
|
//
|
||||||
|
@ -424,13 +423,13 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
//
|
//
|
||||||
TempPde.u.Hard.PageFrameNumber = MxGetNextPage(1);
|
TempPde.u.Hard.PageFrameNumber = MxGetNextPage(1);
|
||||||
MI_WRITE_VALID_PTE(StartPde, TempPde);
|
MI_WRITE_VALID_PTE(StartPde, TempPde);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Zero out the page table
|
// Zero out the page table
|
||||||
//
|
//
|
||||||
PointerPte = MiPteToAddress(StartPde);
|
PointerPte = MiPteToAddress(StartPde);
|
||||||
RtlZeroMemory(PointerPte, PAGE_SIZE);
|
RtlZeroMemory(PointerPte, PAGE_SIZE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Next
|
// Next
|
||||||
//
|
//
|
||||||
|
@ -456,7 +455,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
//
|
//
|
||||||
PointerPte = MiPteToAddress(StartPde);
|
PointerPte = MiPteToAddress(StartPde);
|
||||||
RtlZeroMemory(PointerPte, PAGE_SIZE);
|
RtlZeroMemory(PointerPte, PAGE_SIZE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Next
|
// Next
|
||||||
//
|
//
|
||||||
|
@ -482,23 +481,23 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
TempPte.u.Hard.PageFrameNumber = PageFrameIndex++;
|
TempPte.u.Hard.PageFrameNumber = PageFrameIndex++;
|
||||||
MI_WRITE_VALID_PTE(PointerPte++, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte++, TempPte);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity check: make sure we have properly defined the system PTE space
|
// Sanity check: make sure we have properly defined the system PTE space
|
||||||
//
|
//
|
||||||
ASSERT(MiAddressToPte(MmNonPagedSystemStart) <
|
ASSERT(MiAddressToPte(MmNonPagedSystemStart) <
|
||||||
MiAddressToPte(MmNonPagedPoolExpansionStart));
|
MiAddressToPte(MmNonPagedPoolExpansionStart));
|
||||||
|
|
||||||
/* Now go ahead and initialize the nonpaged pool */
|
/* Now go ahead and initialize the nonpaged pool */
|
||||||
MiInitializeNonPagedPool();
|
MiInitializeNonPagedPool();
|
||||||
MiInitializeNonPagedPoolThresholds();
|
MiInitializeNonPagedPoolThresholds();
|
||||||
|
|
||||||
/* Map the PFN database pages */
|
/* Map the PFN database pages */
|
||||||
MiMapPfnDatabase(LoaderBlock);
|
MiMapPfnDatabase(LoaderBlock);
|
||||||
|
|
||||||
/* Initialize the color tables */
|
/* Initialize the color tables */
|
||||||
MiInitializeColorTables();
|
MiInitializeColorTables();
|
||||||
|
|
||||||
/* Build the PFN Database */
|
/* Build the PFN Database */
|
||||||
MiInitializePfnDatabase(LoaderBlock);
|
MiInitializePfnDatabase(LoaderBlock);
|
||||||
MmInitializeBalancer(MmAvailablePages, 0);
|
MmInitializeBalancer(MmAvailablePages, 0);
|
||||||
|
@ -507,12 +506,12 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
// Reset the descriptor back so we can create the correct memory blocks
|
// Reset the descriptor back so we can create the correct memory blocks
|
||||||
//
|
//
|
||||||
*MxFreeDescriptor = MxOldFreeDescriptor;
|
*MxFreeDescriptor = MxOldFreeDescriptor;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize the nonpaged pool
|
// Initialize the nonpaged pool
|
||||||
//
|
//
|
||||||
InitializePool(NonPagedPool, 0);
|
InitializePool(NonPagedPool, 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// We PDE-aligned the nonpaged system start VA, so haul some extra PTEs!
|
// We PDE-aligned the nonpaged system start VA, so haul some extra PTEs!
|
||||||
//
|
//
|
||||||
|
@ -522,18 +521,18 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
MmNumberOfSystemPtes--;
|
MmNumberOfSystemPtes--;
|
||||||
DPRINT("Final System PTE count: %d (%d bytes)\n",
|
DPRINT("Final System PTE count: %d (%d bytes)\n",
|
||||||
MmNumberOfSystemPtes, MmNumberOfSystemPtes * PAGE_SIZE);
|
MmNumberOfSystemPtes, MmNumberOfSystemPtes * PAGE_SIZE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create the system PTE space
|
// Create the system PTE space
|
||||||
//
|
//
|
||||||
MiInitializeSystemPtes(PointerPte, MmNumberOfSystemPtes, SystemPteSpace);
|
MiInitializeSystemPtes(PointerPte, MmNumberOfSystemPtes, SystemPteSpace);
|
||||||
|
|
||||||
/* Get the PDE For hyperspace */
|
/* Get the PDE For hyperspace */
|
||||||
StartPde = MiAddressToPde(HYPER_SPACE);
|
StartPde = MiAddressToPde(HYPER_SPACE);
|
||||||
|
|
||||||
/* Lock PFN database */
|
/* Lock PFN database */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
/* Allocate a page for hyperspace and create it */
|
/* Allocate a page for hyperspace and create it */
|
||||||
MI_SET_USAGE(MI_USAGE_PAGE_TABLE);
|
MI_SET_USAGE(MI_USAGE_PAGE_TABLE);
|
||||||
MI_SET_PROCESS2("Kernel");
|
MI_SET_PROCESS2("Kernel");
|
||||||
|
@ -541,26 +540,26 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
TempPde.u.Hard.PageFrameNumber = PageFrameIndex;
|
TempPde.u.Hard.PageFrameNumber = PageFrameIndex;
|
||||||
TempPde.u.Hard.Global = FALSE; // Hyperspace is local!
|
TempPde.u.Hard.Global = FALSE; // Hyperspace is local!
|
||||||
MI_WRITE_VALID_PTE(StartPde, TempPde);
|
MI_WRITE_VALID_PTE(StartPde, TempPde);
|
||||||
|
|
||||||
/* Flush the TLB */
|
/* Flush the TLB */
|
||||||
KeFlushCurrentTb();
|
KeFlushCurrentTb();
|
||||||
|
|
||||||
/* Release the lock */
|
/* Release the lock */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Zero out the page table now
|
// Zero out the page table now
|
||||||
//
|
//
|
||||||
PointerPte = MiAddressToPte(HYPER_SPACE);
|
PointerPte = MiAddressToPte(HYPER_SPACE);
|
||||||
RtlZeroMemory(PointerPte, PAGE_SIZE);
|
RtlZeroMemory(PointerPte, PAGE_SIZE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup the mapping PTEs
|
// Setup the mapping PTEs
|
||||||
//
|
//
|
||||||
MmFirstReservedMappingPte = MiAddressToPte(MI_MAPPING_RANGE_START);
|
MmFirstReservedMappingPte = MiAddressToPte(MI_MAPPING_RANGE_START);
|
||||||
MmLastReservedMappingPte = MiAddressToPte(MI_MAPPING_RANGE_END);
|
MmLastReservedMappingPte = MiAddressToPte(MI_MAPPING_RANGE_END);
|
||||||
MmFirstReservedMappingPte->u.Hard.PageFrameNumber = MI_HYPERSPACE_PTES;
|
MmFirstReservedMappingPte->u.Hard.PageFrameNumber = MI_HYPERSPACE_PTES;
|
||||||
|
|
||||||
/* Set the working set address */
|
/* Set the working set address */
|
||||||
MmWorkingSetList = (PVOID)MI_WORKING_SET_LIST;
|
MmWorkingSetList = (PVOID)MI_WORKING_SET_LIST;
|
||||||
|
|
||||||
|
@ -570,39 +569,39 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
MiFirstReservedZeroingPte = MiReserveSystemPtes(MI_ZERO_PTES,
|
MiFirstReservedZeroingPte = MiReserveSystemPtes(MI_ZERO_PTES,
|
||||||
SystemPteSpace);
|
SystemPteSpace);
|
||||||
RtlZeroMemory(MiFirstReservedZeroingPte, MI_ZERO_PTES * sizeof(MMPTE));
|
RtlZeroMemory(MiFirstReservedZeroingPte, MI_ZERO_PTES * sizeof(MMPTE));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set the counter to maximum to boot with
|
// Set the counter to maximum to boot with
|
||||||
//
|
//
|
||||||
MiFirstReservedZeroingPte->u.Hard.PageFrameNumber = MI_ZERO_PTES - 1;
|
MiFirstReservedZeroingPte->u.Hard.PageFrameNumber = MI_ZERO_PTES - 1;
|
||||||
|
|
||||||
/* Lock PFN database */
|
/* Lock PFN database */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
/* Reset the ref/share count so that MmInitializeProcessAddressSpace works */
|
/* Reset the ref/share count so that MmInitializeProcessAddressSpace works */
|
||||||
Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(MiAddressToPde(PDE_BASE)));
|
Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(MiAddressToPde(PDE_BASE)));
|
||||||
Pfn1->u2.ShareCount = 0;
|
Pfn1->u2.ShareCount = 0;
|
||||||
Pfn1->u3.e2.ReferenceCount = 0;
|
Pfn1->u3.e2.ReferenceCount = 0;
|
||||||
|
|
||||||
/* Get a page for the working set list */
|
/* Get a page for the working set list */
|
||||||
MI_SET_USAGE(MI_USAGE_PAGE_TABLE);
|
MI_SET_USAGE(MI_USAGE_PAGE_TABLE);
|
||||||
MI_SET_PROCESS2("Kernel WS List");
|
MI_SET_PROCESS2("Kernel WS List");
|
||||||
PageFrameIndex = MiRemoveAnyPage(0);
|
PageFrameIndex = MiRemoveAnyPage(0);
|
||||||
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
||||||
|
|
||||||
/* Map the working set list */
|
/* Map the working set list */
|
||||||
PointerPte = MiAddressToPte(MmWorkingSetList);
|
PointerPte = MiAddressToPte(MmWorkingSetList);
|
||||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
|
||||||
/* Zero it out, and save the frame index */
|
/* Zero it out, and save the frame index */
|
||||||
RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
|
RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
|
||||||
PsGetCurrentProcess()->WorkingSetPage = PageFrameIndex;
|
PsGetCurrentProcess()->WorkingSetPage = PageFrameIndex;
|
||||||
|
|
||||||
/* Check for Pentium LOCK errata */
|
/* Check for Pentium LOCK errata */
|
||||||
if (KiI386PentiumLockErrataPresent)
|
if (KiI386PentiumLockErrataPresent)
|
||||||
{
|
{
|
||||||
/* Mark the 1st IDT page as Write-Through to prevent a lockup
|
/* Mark the 1st IDT page as Write-Through to prevent a lockup
|
||||||
on a F00F instruction.
|
on a F00F instruction.
|
||||||
See http://www.rcollins.org/Errata/Dec97/F00FBug.html */
|
See http://www.rcollins.org/Errata/Dec97/F00FBug.html */
|
||||||
PointerPte = MiAddressToPte(KeGetPcr()->IDT);
|
PointerPte = MiAddressToPte(KeGetPcr()->IDT);
|
||||||
PointerPte->u.Hard.WriteThrough = 1;
|
PointerPte->u.Hard.WriteThrough = 1;
|
||||||
|
@ -614,7 +613,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
/* Initialize the bogus address space */
|
/* Initialize the bogus address space */
|
||||||
Flags = 0;
|
Flags = 0;
|
||||||
MmInitializeProcessAddressSpace(PsGetCurrentProcess(), NULL, NULL, &Flags, NULL);
|
MmInitializeProcessAddressSpace(PsGetCurrentProcess(), NULL, NULL, &Flags, NULL);
|
||||||
|
|
||||||
/* Make sure the color lists are valid */
|
/* Make sure the color lists are valid */
|
||||||
ASSERT(MmFreePagesByColor[0] < (PMMCOLOR_TABLES)PTE_BASE);
|
ASSERT(MmFreePagesByColor[0] < (PMMCOLOR_TABLES)PTE_BASE);
|
||||||
StartPde = MiAddressToPde(MmFreePagesByColor[0]);
|
StartPde = MiAddressToPde(MmFreePagesByColor[0]);
|
||||||
|
@ -639,11 +638,11 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
||||||
Pfn1->u3.e1.CacheAttribute = MiCached;
|
Pfn1->u3.e1.CacheAttribute = MiCached;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep going */
|
/* Keep going */
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All done */
|
/* All done */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::IOSUP"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -49,7 +48,7 @@ MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
IN SIZE_T NumberOfBytes,
|
IN SIZE_T NumberOfBytes,
|
||||||
IN MEMORY_CACHING_TYPE CacheType)
|
IN MEMORY_CACHING_TYPE CacheType)
|
||||||
{
|
{
|
||||||
|
|
||||||
PFN_NUMBER Pfn, PageCount;
|
PFN_NUMBER Pfn, PageCount;
|
||||||
PMMPTE PointerPte;
|
PMMPTE PointerPte;
|
||||||
PVOID BaseAddress;
|
PVOID BaseAddress;
|
||||||
|
@ -78,13 +77,13 @@ MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
//
|
//
|
||||||
CacheType &= 0xFF;
|
CacheType &= 0xFF;
|
||||||
if (CacheType >= MmMaximumCacheType) return NULL;
|
if (CacheType >= MmMaximumCacheType) return NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Calculate page count
|
// Calculate page count
|
||||||
//
|
//
|
||||||
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(PhysicalAddress.LowPart,
|
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(PhysicalAddress.LowPart,
|
||||||
NumberOfBytes);
|
NumberOfBytes);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Compute the PFN and check if it's a known I/O mapping
|
// Compute the PFN and check if it's a known I/O mapping
|
||||||
// Also translate the cache attribute
|
// Also translate the cache attribute
|
||||||
|
@ -93,14 +92,14 @@ MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
Pfn1 = MiGetPfnEntry(Pfn);
|
Pfn1 = MiGetPfnEntry(Pfn);
|
||||||
IsIoMapping = (Pfn1 == NULL) ? TRUE : FALSE;
|
IsIoMapping = (Pfn1 == NULL) ? TRUE : FALSE;
|
||||||
CacheAttribute = MiPlatformCacheAttributes[IsIoMapping][CacheType];
|
CacheAttribute = MiPlatformCacheAttributes[IsIoMapping][CacheType];
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now allocate system PTEs for the mapping, and get the VA
|
// Now allocate system PTEs for the mapping, and get the VA
|
||||||
//
|
//
|
||||||
PointerPte = MiReserveSystemPtes(PageCount, SystemPteSpace);
|
PointerPte = MiReserveSystemPtes(PageCount, SystemPteSpace);
|
||||||
if (!PointerPte) return NULL;
|
if (!PointerPte) return NULL;
|
||||||
BaseAddress = MiPteToAddress(PointerPte);
|
BaseAddress = MiPteToAddress(PointerPte);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is uncached
|
// Check if this is uncached
|
||||||
//
|
//
|
||||||
|
@ -112,13 +111,13 @@ MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
KeFlushEntireTb(TRUE, TRUE);
|
KeFlushEntireTb(TRUE, TRUE);
|
||||||
KeInvalidateAllCaches();
|
KeInvalidateAllCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now compute the VA offset
|
// Now compute the VA offset
|
||||||
//
|
//
|
||||||
BaseAddress = (PVOID)((ULONG_PTR)BaseAddress +
|
BaseAddress = (PVOID)((ULONG_PTR)BaseAddress +
|
||||||
BYTE_OFFSET(PhysicalAddress.LowPart));
|
BYTE_OFFSET(PhysicalAddress.LowPart));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the template and configure caching
|
// Get the template and configure caching
|
||||||
//
|
//
|
||||||
|
@ -126,38 +125,38 @@ MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
switch (CacheAttribute)
|
switch (CacheAttribute)
|
||||||
{
|
{
|
||||||
case MiNonCached:
|
case MiNonCached:
|
||||||
|
|
||||||
//
|
//
|
||||||
// Disable the cache
|
// Disable the cache
|
||||||
//
|
//
|
||||||
MI_PAGE_DISABLE_CACHE(&TempPte);
|
MI_PAGE_DISABLE_CACHE(&TempPte);
|
||||||
MI_PAGE_WRITE_THROUGH(&TempPte);
|
MI_PAGE_WRITE_THROUGH(&TempPte);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MiCached:
|
case MiCached:
|
||||||
|
|
||||||
//
|
//
|
||||||
// Leave defaults
|
// Leave defaults
|
||||||
//
|
//
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MiWriteCombined:
|
case MiWriteCombined:
|
||||||
|
|
||||||
//
|
//
|
||||||
// We don't support write combining yet
|
// We don't support write combining yet
|
||||||
//
|
//
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
//
|
//
|
||||||
// Should never happen
|
// Should never happen
|
||||||
//
|
//
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity check and re-flush
|
// Sanity check and re-flush
|
||||||
//
|
//
|
||||||
|
@ -165,7 +164,7 @@ MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
ASSERT((Pfn1 == MiGetPfnEntry(Pfn)) || (Pfn1 == NULL));
|
ASSERT((Pfn1 == MiGetPfnEntry(Pfn)) || (Pfn1 == NULL));
|
||||||
KeFlushEntireTb(TRUE, TRUE);
|
KeFlushEntireTb(TRUE, TRUE);
|
||||||
KeInvalidateAllCaches();
|
KeInvalidateAllCaches();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Do the mapping
|
// Do the mapping
|
||||||
//
|
//
|
||||||
|
@ -177,7 +176,7 @@ MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
TempPte.u.Hard.PageFrameNumber = Pfn++;
|
TempPte.u.Hard.PageFrameNumber = Pfn++;
|
||||||
MI_WRITE_VALID_PTE(PointerPte++, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte++, TempPte);
|
||||||
} while (--PageCount);
|
} while (--PageCount);
|
||||||
|
|
||||||
//
|
//
|
||||||
// We're done!
|
// We're done!
|
||||||
//
|
//
|
||||||
|
@ -191,26 +190,26 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmUnmapIoSpace(IN PVOID BaseAddress,
|
MmUnmapIoSpace(IN PVOID BaseAddress,
|
||||||
IN SIZE_T NumberOfBytes)
|
IN SIZE_T NumberOfBytes)
|
||||||
{
|
{
|
||||||
PFN_NUMBER PageCount, Pfn;
|
PFN_NUMBER PageCount, Pfn;
|
||||||
PMMPTE PointerPte;
|
PMMPTE PointerPte;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity check
|
// Sanity check
|
||||||
//
|
//
|
||||||
ASSERT(NumberOfBytes != 0);
|
ASSERT(NumberOfBytes != 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the page count
|
// Get the page count
|
||||||
//
|
//
|
||||||
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, NumberOfBytes);
|
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, NumberOfBytes);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the PTE and PFN
|
// Get the PTE and PFN
|
||||||
//
|
//
|
||||||
PointerPte = MiAddressToPte(BaseAddress);
|
PointerPte = MiAddressToPte(BaseAddress);
|
||||||
Pfn = PFN_FROM_PTE(PointerPte);
|
Pfn = PFN_FROM_PTE(PointerPte);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Is this an I/O mapping?
|
// Is this an I/O mapping?
|
||||||
//
|
//
|
||||||
|
@ -220,13 +219,13 @@ MmUnmapIoSpace(IN PVOID BaseAddress,
|
||||||
// Destroy the PTE
|
// Destroy the PTE
|
||||||
//
|
//
|
||||||
RtlZeroMemory(PointerPte, PageCount * sizeof(MMPTE));
|
RtlZeroMemory(PointerPte, PageCount * sizeof(MMPTE));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Blow the TLB
|
// Blow the TLB
|
||||||
//
|
//
|
||||||
KeFlushEntireTb(TRUE, TRUE);
|
KeFlushEntireTb(TRUE, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the PTEs
|
// Release the PTEs
|
||||||
//
|
//
|
||||||
|
@ -243,7 +242,7 @@ MmMapVideoDisplay(IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
IN MEMORY_CACHING_TYPE CacheType)
|
IN MEMORY_CACHING_TYPE CacheType)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Call the real function
|
// Call the real function
|
||||||
//
|
//
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::LARGEPAGE"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -46,7 +45,7 @@ MiInitializeLargePageSupport(VOID)
|
||||||
/* Initialize the process tracking list, and insert the system process */
|
/* Initialize the process tracking list, and insert the system process */
|
||||||
InitializeListHead(&MmProcessList);
|
InitializeListHead(&MmProcessList);
|
||||||
InsertTailList(&MmProcessList, &PsGetCurrentProcess()->MmProcessLinks);
|
InsertTailList(&MmProcessList, &PsGetCurrentProcess()->MmProcessLinks);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -89,7 +88,7 @@ MiInitializeDriverLargePageList(VOID)
|
||||||
p++;
|
p++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A star means everything */
|
/* A star means everything */
|
||||||
if (*p == L'*')
|
if (*p == L'*')
|
||||||
{
|
{
|
||||||
|
@ -97,7 +96,7 @@ MiInitializeDriverLargePageList(VOID)
|
||||||
MiLargePageAllDrivers = TRUE;
|
MiLargePageAllDrivers = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT1("Large page drivers not supported\n");
|
DPRINT1("Large page drivers not supported\n");
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,11 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::MDLSUP"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
/* GLOBALS ********************************************************************/
|
/* GLOBALS ********************************************************************/
|
||||||
|
|
||||||
BOOLEAN MmTrackPtes;
|
BOOLEAN MmTrackPtes;
|
||||||
BOOLEAN MmTrackLockedPages;
|
BOOLEAN MmTrackLockedPages;
|
||||||
SIZE_T MmSystemLockPagesCount;
|
SIZE_T MmSystemLockPagesCount;
|
||||||
|
@ -34,7 +33,7 @@ MmCreateMdl(IN PMDL Mdl,
|
||||||
IN SIZE_T Length)
|
IN SIZE_T Length)
|
||||||
{
|
{
|
||||||
SIZE_T Size;
|
SIZE_T Size;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we don't have an MDL built
|
// Check if we don't have an MDL built
|
||||||
//
|
//
|
||||||
|
@ -47,7 +46,7 @@ MmCreateMdl(IN PMDL Mdl,
|
||||||
Mdl = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MDL);
|
Mdl = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MDL);
|
||||||
if (!Mdl) return NULL;
|
if (!Mdl) return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize it
|
// Initialize it
|
||||||
//
|
//
|
||||||
|
@ -81,7 +80,7 @@ MmBuildMdlForNonPagedPool(IN PMDL Mdl)
|
||||||
PFN_NUMBER Pfn, PageCount;
|
PFN_NUMBER Pfn, PageCount;
|
||||||
PVOID Base;
|
PVOID Base;
|
||||||
PMMPTE PointerPte;
|
PMMPTE PointerPte;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
//
|
//
|
||||||
|
@ -89,19 +88,19 @@ MmBuildMdlForNonPagedPool(IN PMDL Mdl)
|
||||||
ASSERT((Mdl->MdlFlags & (MDL_PAGES_LOCKED |
|
ASSERT((Mdl->MdlFlags & (MDL_PAGES_LOCKED |
|
||||||
MDL_MAPPED_TO_SYSTEM_VA |
|
MDL_MAPPED_TO_SYSTEM_VA |
|
||||||
MDL_SOURCE_IS_NONPAGED_POOL |
|
MDL_SOURCE_IS_NONPAGED_POOL |
|
||||||
MDL_PARTIAL)) == 0);
|
MDL_PARTIAL)) == 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// We know the MDL isn't associated to a process now
|
// We know the MDL isn't associated to a process now
|
||||||
//
|
//
|
||||||
Mdl->Process = NULL;
|
Mdl->Process = NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get page and VA information
|
// Get page and VA information
|
||||||
//
|
//
|
||||||
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
||||||
Base = Mdl->StartVa;
|
Base = Mdl->StartVa;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set the system address and now get the page count
|
// Set the system address and now get the page count
|
||||||
//
|
//
|
||||||
|
@ -110,7 +109,7 @@ MmBuildMdlForNonPagedPool(IN PMDL Mdl)
|
||||||
Mdl->ByteCount);
|
Mdl->ByteCount);
|
||||||
ASSERT(PageCount != 0);
|
ASSERT(PageCount != 0);
|
||||||
EndPage = MdlPages + PageCount;
|
EndPage = MdlPages + PageCount;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop the PTEs
|
// Loop the PTEs
|
||||||
//
|
//
|
||||||
|
@ -123,12 +122,12 @@ MmBuildMdlForNonPagedPool(IN PMDL Mdl)
|
||||||
Pfn = PFN_FROM_PTE(PointerPte++);
|
Pfn = PFN_FROM_PTE(PointerPte++);
|
||||||
*MdlPages++ = Pfn;
|
*MdlPages++ = Pfn;
|
||||||
} while (MdlPages < EndPage);
|
} while (MdlPages < EndPage);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set the nonpaged pool flag
|
// Set the nonpaged pool flag
|
||||||
//
|
//
|
||||||
Mdl->MdlFlags |= MDL_SOURCE_IS_NONPAGED_POOL;
|
Mdl->MdlFlags |= MDL_SOURCE_IS_NONPAGED_POOL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is an I/O mapping
|
// Check if this is an I/O mapping
|
||||||
//
|
//
|
||||||
|
@ -169,7 +168,7 @@ MmAllocatePagesForMdlEx(IN PHYSICAL_ADDRESS LowAddress,
|
||||||
IN ULONG Flags)
|
IN ULONG Flags)
|
||||||
{
|
{
|
||||||
MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
|
MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check for invalid cache type
|
// Check for invalid cache type
|
||||||
//
|
//
|
||||||
|
@ -187,7 +186,7 @@ MmAllocatePagesForMdlEx(IN PHYSICAL_ADDRESS LowAddress,
|
||||||
//
|
//
|
||||||
CacheAttribute = MiPlatformCacheAttributes[FALSE][CacheType];
|
CacheAttribute = MiPlatformCacheAttributes[FALSE][CacheType];
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Only these flags are allowed
|
// Only these flags are allowed
|
||||||
//
|
//
|
||||||
|
@ -198,7 +197,7 @@ MmAllocatePagesForMdlEx(IN PHYSICAL_ADDRESS LowAddress,
|
||||||
//
|
//
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Call the internal routine
|
// Call the internal routine
|
||||||
//
|
//
|
||||||
|
@ -223,14 +222,14 @@ MmFreePagesFromMdl(IN PMDL Mdl)
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
DPRINT("Freeing MDL: %p\n", Mdl);
|
DPRINT("Freeing MDL: %p\n", Mdl);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
//
|
//
|
||||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||||
ASSERT((Mdl->MdlFlags & MDL_IO_SPACE) == 0);
|
ASSERT((Mdl->MdlFlags & MDL_IO_SPACE) == 0);
|
||||||
ASSERT(((ULONG_PTR)Mdl->StartVa & (PAGE_SIZE - 1)) == 0);
|
ASSERT(((ULONG_PTR)Mdl->StartVa & (PAGE_SIZE - 1)) == 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get address and page information
|
// Get address and page information
|
||||||
//
|
//
|
||||||
|
@ -260,19 +259,19 @@ MmFreePagesFromMdl(IN PMDL Mdl)
|
||||||
ASSERT(Pfn1);
|
ASSERT(Pfn1);
|
||||||
ASSERT(Pfn1->u2.ShareCount == 1);
|
ASSERT(Pfn1->u2.ShareCount == 1);
|
||||||
ASSERT(MI_IS_PFN_DELETED(Pfn1) == TRUE);
|
ASSERT(MI_IS_PFN_DELETED(Pfn1) == TRUE);
|
||||||
if (Pfn1->u4.PteFrame != 0x1FFEDCB)
|
if (Pfn1->u4.PteFrame != 0x1FFEDCB)
|
||||||
{
|
{
|
||||||
/* Corrupted PFN entry or invalid free */
|
/* Corrupted PFN entry or invalid free */
|
||||||
KeBugCheckEx(MEMORY_MANAGEMENT, 0x1236, (ULONG_PTR)Mdl, (ULONG_PTR)Pages, *Pages);
|
KeBugCheckEx(MEMORY_MANAGEMENT, 0x1236, (ULONG_PTR)Mdl, (ULONG_PTR)Pages, *Pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Clear it
|
// Clear it
|
||||||
//
|
//
|
||||||
Pfn1->u3.e1.StartOfAllocation = 0;
|
Pfn1->u3.e1.StartOfAllocation = 0;
|
||||||
Pfn1->u3.e1.EndOfAllocation = 0;
|
Pfn1->u3.e1.EndOfAllocation = 0;
|
||||||
Pfn1->u2.ShareCount = 0;
|
Pfn1->u2.ShareCount = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Dereference it
|
// Dereference it
|
||||||
//
|
//
|
||||||
|
@ -287,7 +286,7 @@ MmFreePagesFromMdl(IN PMDL Mdl)
|
||||||
/* We'll be nuking the whole page */
|
/* We'll be nuking the whole page */
|
||||||
MiDecrementReferenceCount(Pfn1, *Pages);
|
MiDecrementReferenceCount(Pfn1, *Pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Clear this page and move on
|
// Clear this page and move on
|
||||||
//
|
//
|
||||||
|
@ -324,17 +323,17 @@ MmMapLockedPagesSpecifyCache(IN PMDL Mdl,
|
||||||
MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
|
MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
|
||||||
PMMPTE PointerPte;
|
PMMPTE PointerPte;
|
||||||
MMPTE TempPte;
|
MMPTE TempPte;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity check
|
// Sanity check
|
||||||
//
|
//
|
||||||
ASSERT(Mdl->ByteCount != 0);
|
ASSERT(Mdl->ByteCount != 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the base
|
// Get the base
|
||||||
//
|
//
|
||||||
Base = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset);
|
Base = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle kernel case first
|
// Handle kernel case first
|
||||||
//
|
//
|
||||||
|
@ -346,7 +345,7 @@ MmMapLockedPagesSpecifyCache(IN PMDL Mdl,
|
||||||
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
||||||
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base, Mdl->ByteCount);
|
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base, Mdl->ByteCount);
|
||||||
LastPage = MdlPages + PageCount;
|
LastPage = MdlPages + PageCount;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
//
|
//
|
||||||
|
@ -354,13 +353,13 @@ MmMapLockedPagesSpecifyCache(IN PMDL Mdl,
|
||||||
MDL_SOURCE_IS_NONPAGED_POOL |
|
MDL_SOURCE_IS_NONPAGED_POOL |
|
||||||
MDL_PARTIAL_HAS_BEEN_MAPPED)) == 0);
|
MDL_PARTIAL_HAS_BEEN_MAPPED)) == 0);
|
||||||
ASSERT((Mdl->MdlFlags & (MDL_PAGES_LOCKED | MDL_PARTIAL)) != 0);
|
ASSERT((Mdl->MdlFlags & (MDL_PAGES_LOCKED | MDL_PARTIAL)) != 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the correct cache type
|
// Get the correct cache type
|
||||||
//
|
//
|
||||||
IsIoMapping = (Mdl->MdlFlags & MDL_IO_SPACE) != 0;
|
IsIoMapping = (Mdl->MdlFlags & MDL_IO_SPACE) != 0;
|
||||||
CacheAttribute = MiPlatformCacheAttributes[IsIoMapping][CacheType];
|
CacheAttribute = MiPlatformCacheAttributes[IsIoMapping][CacheType];
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reserve the PTEs
|
// Reserve the PTEs
|
||||||
//
|
//
|
||||||
|
@ -371,23 +370,23 @@ MmMapLockedPagesSpecifyCache(IN PMDL Mdl,
|
||||||
// If it can fail, return NULL
|
// If it can fail, return NULL
|
||||||
//
|
//
|
||||||
if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL) return NULL;
|
if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL) return NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Should we bugcheck?
|
// Should we bugcheck?
|
||||||
//
|
//
|
||||||
if (!BugCheckOnFailure) return NULL;
|
if (!BugCheckOnFailure) return NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Yes, crash the system
|
// Yes, crash the system
|
||||||
//
|
//
|
||||||
KeBugCheckEx(NO_MORE_SYSTEM_PTES, 0, PageCount, 0, 0);
|
KeBugCheckEx(NO_MORE_SYSTEM_PTES, 0, PageCount, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the mapped address
|
// Get the mapped address
|
||||||
//
|
//
|
||||||
Base = (PVOID)((ULONG_PTR)MiPteToAddress(PointerPte) + Mdl->ByteOffset);
|
Base = (PVOID)((ULONG_PTR)MiPteToAddress(PointerPte) + Mdl->ByteOffset);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the template
|
// Get the template
|
||||||
//
|
//
|
||||||
|
@ -395,30 +394,30 @@ MmMapLockedPagesSpecifyCache(IN PMDL Mdl,
|
||||||
switch (CacheAttribute)
|
switch (CacheAttribute)
|
||||||
{
|
{
|
||||||
case MiNonCached:
|
case MiNonCached:
|
||||||
|
|
||||||
//
|
//
|
||||||
// Disable caching
|
// Disable caching
|
||||||
//
|
//
|
||||||
MI_PAGE_DISABLE_CACHE(&TempPte);
|
MI_PAGE_DISABLE_CACHE(&TempPte);
|
||||||
MI_PAGE_WRITE_THROUGH(&TempPte);
|
MI_PAGE_WRITE_THROUGH(&TempPte);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MiWriteCombined:
|
case MiWriteCombined:
|
||||||
|
|
||||||
//
|
//
|
||||||
// Enable write combining
|
// Enable write combining
|
||||||
//
|
//
|
||||||
MI_PAGE_DISABLE_CACHE(&TempPte);
|
MI_PAGE_DISABLE_CACHE(&TempPte);
|
||||||
MI_PAGE_WRITE_COMBINED(&TempPte);
|
MI_PAGE_WRITE_COMBINED(&TempPte);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
//
|
//
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
//
|
//
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop all PTEs
|
// Loop all PTEs
|
||||||
//
|
//
|
||||||
|
@ -428,21 +427,21 @@ MmMapLockedPagesSpecifyCache(IN PMDL Mdl,
|
||||||
// We're done here
|
// We're done here
|
||||||
//
|
//
|
||||||
if (*MdlPages == LIST_HEAD) break;
|
if (*MdlPages == LIST_HEAD) break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Write the PTE
|
// Write the PTE
|
||||||
//
|
//
|
||||||
TempPte.u.Hard.PageFrameNumber = *MdlPages;
|
TempPte.u.Hard.PageFrameNumber = *MdlPages;
|
||||||
MI_WRITE_VALID_PTE(PointerPte++, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte++, TempPte);
|
||||||
} while (++MdlPages < LastPage);
|
} while (++MdlPages < LastPage);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Mark it as mapped
|
// Mark it as mapped
|
||||||
//
|
//
|
||||||
ASSERT((Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) == 0);
|
ASSERT((Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) == 0);
|
||||||
Mdl->MappedSystemVa = Base;
|
Mdl->MappedSystemVa = Base;
|
||||||
Mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
|
Mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if it was partial
|
// Check if it was partial
|
||||||
//
|
//
|
||||||
|
@ -453,13 +452,13 @@ MmMapLockedPagesSpecifyCache(IN PMDL Mdl,
|
||||||
//
|
//
|
||||||
Mdl->MdlFlags |= MDL_PARTIAL_HAS_BEEN_MAPPED;
|
Mdl->MdlFlags |= MDL_PARTIAL_HAS_BEEN_MAPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return the mapped address
|
// Return the mapped address
|
||||||
//
|
//
|
||||||
return Base;
|
return Base;
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -495,12 +494,12 @@ MmUnmapLockedPages(IN PVOID BaseAddress,
|
||||||
PFN_NUMBER PageCount;
|
PFN_NUMBER PageCount;
|
||||||
PPFN_NUMBER MdlPages;
|
PPFN_NUMBER MdlPages;
|
||||||
PMMPTE PointerPte;
|
PMMPTE PointerPte;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity check
|
// Sanity check
|
||||||
//
|
//
|
||||||
ASSERT(Mdl->ByteCount != 0);
|
ASSERT(Mdl->ByteCount != 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is a kernel request
|
// Check if this is a kernel request
|
||||||
//
|
//
|
||||||
|
@ -511,14 +510,14 @@ MmUnmapLockedPages(IN PVOID BaseAddress,
|
||||||
//
|
//
|
||||||
Base = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset);
|
Base = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset);
|
||||||
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base, Mdl->ByteCount);
|
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base, Mdl->ByteCount);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
//
|
//
|
||||||
ASSERT((Mdl->MdlFlags & MDL_PARENT_MAPPED_SYSTEM_VA) == 0);
|
ASSERT((Mdl->MdlFlags & MDL_PARENT_MAPPED_SYSTEM_VA) == 0);
|
||||||
ASSERT(PageCount != 0);
|
ASSERT(PageCount != 0);
|
||||||
ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
|
ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the PTE
|
// Get the PTE
|
||||||
//
|
//
|
||||||
|
@ -530,7 +529,7 @@ MmUnmapLockedPages(IN PVOID BaseAddress,
|
||||||
ASSERT(PointerPte >= MmSystemPtesStart[SystemPteSpace]);
|
ASSERT(PointerPte >= MmSystemPtesStart[SystemPteSpace]);
|
||||||
ASSERT(PointerPte <= MmSystemPtesEnd[SystemPteSpace]);
|
ASSERT(PointerPte <= MmSystemPtesEnd[SystemPteSpace]);
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 1);
|
ASSERT(PointerPte->u.Hard.Valid == 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if the caller wants us to free advanced pages
|
// Check if the caller wants us to free advanced pages
|
||||||
//
|
//
|
||||||
|
@ -541,7 +540,7 @@ MmUnmapLockedPages(IN PVOID BaseAddress,
|
||||||
//
|
//
|
||||||
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
||||||
MdlPages += PageCount;
|
MdlPages += PageCount;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Do the math
|
// Do the math
|
||||||
//
|
//
|
||||||
|
@ -549,21 +548,21 @@ MmUnmapLockedPages(IN PVOID BaseAddress,
|
||||||
PointerPte -= *MdlPages;
|
PointerPte -= *MdlPages;
|
||||||
ASSERT(PointerPte >= MmSystemPtesStart[SystemPteSpace]);
|
ASSERT(PointerPte >= MmSystemPtesStart[SystemPteSpace]);
|
||||||
ASSERT(PointerPte <= MmSystemPtesEnd[SystemPteSpace]);
|
ASSERT(PointerPte <= MmSystemPtesEnd[SystemPteSpace]);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the new base address
|
// Get the new base address
|
||||||
//
|
//
|
||||||
BaseAddress = (PVOID)((ULONG_PTR)BaseAddress -
|
BaseAddress = (PVOID)((ULONG_PTR)BaseAddress -
|
||||||
((*MdlPages) << PAGE_SHIFT));
|
((*MdlPages) << PAGE_SHIFT));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Remove flags
|
// Remove flags
|
||||||
//
|
//
|
||||||
Mdl->MdlFlags &= ~(MDL_MAPPED_TO_SYSTEM_VA |
|
Mdl->MdlFlags &= ~(MDL_MAPPED_TO_SYSTEM_VA |
|
||||||
MDL_PARTIAL_HAS_BEEN_MAPPED |
|
MDL_PARTIAL_HAS_BEEN_MAPPED |
|
||||||
MDL_FREE_EXTRA_PTES);
|
MDL_FREE_EXTRA_PTES);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the system PTEs
|
// Release the system PTEs
|
||||||
//
|
//
|
||||||
|
@ -598,7 +597,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
USHORT OldRefCount, RefCount;
|
USHORT OldRefCount, RefCount;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
DPRINT("Probing MDL: %p\n", Mdl);
|
DPRINT("Probing MDL: %p\n", Mdl);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
//
|
//
|
||||||
|
@ -610,13 +609,13 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
MDL_SOURCE_IS_NONPAGED_POOL |
|
MDL_SOURCE_IS_NONPAGED_POOL |
|
||||||
MDL_PARTIAL |
|
MDL_PARTIAL |
|
||||||
MDL_IO_SPACE)) == 0);
|
MDL_IO_SPACE)) == 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get page and base information
|
// Get page and base information
|
||||||
//
|
//
|
||||||
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
||||||
Base = (PVOID)Mdl->StartVa;
|
Base = (PVOID)Mdl->StartVa;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the addresses and how many pages we span (and need to lock)
|
// Get the addresses and how many pages we span (and need to lock)
|
||||||
//
|
//
|
||||||
|
@ -624,7 +623,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
LastAddress = (PVOID)((ULONG_PTR)Address + Mdl->ByteCount);
|
LastAddress = (PVOID)((ULONG_PTR)Address + Mdl->ByteCount);
|
||||||
LockPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Address, Mdl->ByteCount);
|
LockPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Address, Mdl->ByteCount);
|
||||||
ASSERT(LockPages != 0);
|
ASSERT(LockPages != 0);
|
||||||
|
|
||||||
/* Block invalid access */
|
/* Block invalid access */
|
||||||
if ((AccessMode != KernelMode) &&
|
if ((AccessMode != KernelMode) &&
|
||||||
((LastAddress > (PVOID)MM_USER_PROBE_ADDRESS) || (Address >= LastAddress)))
|
((LastAddress > (PVOID)MM_USER_PROBE_ADDRESS) || (Address >= LastAddress)))
|
||||||
|
@ -633,7 +632,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
*MdlPages = LIST_HEAD;
|
*MdlPages = LIST_HEAD;
|
||||||
ExRaiseStatus(STATUS_ACCESS_VIOLATION);
|
ExRaiseStatus(STATUS_ACCESS_VIOLATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the process
|
// Get the process
|
||||||
//
|
//
|
||||||
|
@ -651,16 +650,16 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
//
|
//
|
||||||
CurrentProcess = NULL;
|
CurrentProcess = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Save the number of pages we'll have to lock, and the start address
|
// Save the number of pages we'll have to lock, and the start address
|
||||||
//
|
//
|
||||||
TotalPages = LockPages;
|
TotalPages = LockPages;
|
||||||
StartAddress = Address;
|
StartAddress = Address;
|
||||||
|
|
||||||
/* Large pages not supported */
|
/* Large pages not supported */
|
||||||
ASSERT(!MI_IS_PHYSICAL_ADDRESS(Address));
|
ASSERT(!MI_IS_PHYSICAL_ADDRESS(Address));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now probe them
|
// Now probe them
|
||||||
//
|
//
|
||||||
|
@ -676,12 +675,12 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
// Assume failure
|
// Assume failure
|
||||||
//
|
//
|
||||||
*MdlPages = LIST_HEAD;
|
*MdlPages = LIST_HEAD;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Read
|
// Read
|
||||||
//
|
//
|
||||||
*(volatile CHAR*)Address;
|
*(volatile CHAR*)Address;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is write access (only probe for user-mode)
|
// Check if this is write access (only probe for user-mode)
|
||||||
//
|
//
|
||||||
|
@ -693,19 +692,19 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
//
|
//
|
||||||
ProbeForWriteChar(Address);
|
ProbeForWriteChar(Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Next address...
|
// Next address...
|
||||||
//
|
//
|
||||||
Address = PAGE_ALIGN((ULONG_PTR)Address + PAGE_SIZE);
|
Address = PAGE_ALIGN((ULONG_PTR)Address + PAGE_SIZE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Next page...
|
// Next page...
|
||||||
//
|
//
|
||||||
LockPages--;
|
LockPages--;
|
||||||
MdlPages++;
|
MdlPages++;
|
||||||
} while (Address < LastAddress);
|
} while (Address < LastAddress);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reset back to the original page
|
// Reset back to the original page
|
||||||
//
|
//
|
||||||
|
@ -720,7 +719,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
ProbeStatus = _SEH2_GetExceptionCode();
|
ProbeStatus = _SEH2_GetExceptionCode();
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
//
|
//
|
||||||
// So how did that go?
|
// So how did that go?
|
||||||
//
|
//
|
||||||
|
@ -733,7 +732,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
Mdl->Process = NULL;
|
Mdl->Process = NULL;
|
||||||
ExRaiseStatus(ProbeStatus);
|
ExRaiseStatus(ProbeStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the PTE and PDE
|
// Get the PTE and PDE
|
||||||
//
|
//
|
||||||
|
@ -743,12 +742,12 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
DPRINT1("PAE/x64 Not Implemented\n");
|
DPRINT1("PAE/x64 Not Implemented\n");
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity check
|
// Sanity check
|
||||||
//
|
//
|
||||||
ASSERT(MdlPages == (PPFN_NUMBER)(Mdl + 1));
|
ASSERT(MdlPages == (PPFN_NUMBER)(Mdl + 1));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check what kind of operation this is
|
// Check what kind of operation this is
|
||||||
//
|
//
|
||||||
|
@ -766,12 +765,12 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
//
|
//
|
||||||
Mdl->MdlFlags &= ~(MDL_WRITE_OPERATION);
|
Mdl->MdlFlags &= ~(MDL_WRITE_OPERATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Mark the MDL as locked *now*
|
// Mark the MDL as locked *now*
|
||||||
//
|
//
|
||||||
Mdl->MdlFlags |= MDL_PAGES_LOCKED;
|
Mdl->MdlFlags |= MDL_PAGES_LOCKED;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this came from kernel mode
|
// Check if this came from kernel mode
|
||||||
//
|
//
|
||||||
|
@ -782,12 +781,12 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
//
|
//
|
||||||
ASSERT(CurrentProcess == NULL);
|
ASSERT(CurrentProcess == NULL);
|
||||||
Mdl->Process = NULL;
|
Mdl->Process = NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// In kernel mode, we don't need to check for write access
|
// In kernel mode, we don't need to check for write access
|
||||||
//
|
//
|
||||||
Operation = IoReadAccess;
|
Operation = IoReadAccess;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Use the PFN lock
|
// Use the PFN lock
|
||||||
//
|
//
|
||||||
|
@ -801,29 +800,29 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
//
|
//
|
||||||
ASSERT(TotalPages != 0);
|
ASSERT(TotalPages != 0);
|
||||||
ASSERT(CurrentProcess == PsGetCurrentProcess());
|
ASSERT(CurrentProcess == PsGetCurrentProcess());
|
||||||
|
|
||||||
//
|
//
|
||||||
// Track locked pages
|
// Track locked pages
|
||||||
//
|
//
|
||||||
InterlockedExchangeAddSizeT(&CurrentProcess->NumberOfLockedPages,
|
InterlockedExchangeAddSizeT(&CurrentProcess->NumberOfLockedPages,
|
||||||
TotalPages);
|
TotalPages);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Save the process
|
// Save the process
|
||||||
//
|
//
|
||||||
Mdl->Process = CurrentProcess;
|
Mdl->Process = CurrentProcess;
|
||||||
|
|
||||||
/* Lock the process working set */
|
/* Lock the process working set */
|
||||||
MiLockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
MiLockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
||||||
UsePfnLock = FALSE;
|
UsePfnLock = FALSE;
|
||||||
OldIrql = MM_NOIRQL;
|
OldIrql = MM_NOIRQL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the last PTE
|
// Get the last PTE
|
||||||
//
|
//
|
||||||
LastPte = MiAddressToPte((PVOID)((ULONG_PTR)LastAddress - 1));
|
LastPte = MiAddressToPte((PVOID)((ULONG_PTR)LastAddress - 1));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop the pages
|
// Loop the pages
|
||||||
//
|
//
|
||||||
|
@ -855,7 +854,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
/* Release process working set */
|
/* Release process working set */
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
MiUnlockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Access the page
|
// Access the page
|
||||||
//
|
//
|
||||||
|
@ -869,7 +868,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
DPRINT1("Access fault failed\n");
|
DPRINT1("Access fault failed\n");
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Waht lock should we use?
|
// Waht lock should we use?
|
||||||
//
|
//
|
||||||
|
@ -886,7 +885,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
MiLockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
MiLockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this was a write or modify
|
// Check if this was a write or modify
|
||||||
//
|
//
|
||||||
|
@ -923,7 +922,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
/* Release process working set */
|
/* Release process working set */
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
MiUnlockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Access the page
|
// Access the page
|
||||||
//
|
//
|
||||||
|
@ -936,7 +935,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
DPRINT1("Access fault failed\n");
|
DPRINT1("Access fault failed\n");
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Re-acquire the lock
|
// Re-acquire the lock
|
||||||
//
|
//
|
||||||
|
@ -952,14 +951,14 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
/* Lock the process working set */
|
/* Lock the process working set */
|
||||||
MiLockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
MiLockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Start over
|
// Start over
|
||||||
//
|
//
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Fail, since we won't allow this
|
// Fail, since we won't allow this
|
||||||
//
|
//
|
||||||
|
@ -967,7 +966,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
goto CleanupWithLock;
|
goto CleanupWithLock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Grab the PFN
|
// Grab the PFN
|
||||||
//
|
//
|
||||||
|
@ -977,10 +976,10 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
{
|
{
|
||||||
/* Either this is for kernel-mode, or the working set is held */
|
/* Either this is for kernel-mode, or the working set is held */
|
||||||
ASSERT((CurrentProcess == NULL) || (UsePfnLock == FALSE));
|
ASSERT((CurrentProcess == NULL) || (UsePfnLock == FALSE));
|
||||||
|
|
||||||
/* No Physical VADs supported yet */
|
/* No Physical VADs supported yet */
|
||||||
if (CurrentProcess) ASSERT(CurrentProcess->PhysicalVadRoot == NULL);
|
if (CurrentProcess) ASSERT(CurrentProcess->PhysicalVadRoot == NULL);
|
||||||
|
|
||||||
/* This address should already exist and be fully valid */
|
/* This address should already exist and be fully valid */
|
||||||
ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
|
ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
|
||||||
if (MI_IS_ROS_PFN(Pfn1))
|
if (MI_IS_ROS_PFN(Pfn1))
|
||||||
|
@ -992,7 +991,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
{
|
{
|
||||||
/* On ARM3 pages, we should see a valid share count */
|
/* On ARM3 pages, we should see a valid share count */
|
||||||
ASSERT((Pfn1->u2.ShareCount != 0) && (Pfn1->u3.e1.PageLocation == ActiveAndValid));
|
ASSERT((Pfn1->u2.ShareCount != 0) && (Pfn1->u3.e1.PageLocation == ActiveAndValid));
|
||||||
|
|
||||||
/* We don't support mapping a prototype page yet */
|
/* We don't support mapping a prototype page yet */
|
||||||
ASSERT((Pfn1->u3.e1.PrototypePte == 0) && (Pfn1->OriginalPte.u.Soft.Prototype == 0));
|
ASSERT((Pfn1->u3.e1.PrototypePte == 0) && (Pfn1->OriginalPte.u.Soft.Prototype == 0));
|
||||||
}
|
}
|
||||||
|
@ -1014,7 +1013,7 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
OldRefCount);
|
OldRefCount);
|
||||||
ASSERT(RefCount != 0);
|
ASSERT(RefCount != 0);
|
||||||
} while (OldRefCount != RefCount);
|
} while (OldRefCount != RefCount);
|
||||||
|
|
||||||
/* Was this the first lock attempt? */
|
/* Was this the first lock attempt? */
|
||||||
if (OldRefCount != 1)
|
if (OldRefCount != 1)
|
||||||
{
|
{
|
||||||
|
@ -1029,17 +1028,17 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
//
|
//
|
||||||
Mdl->MdlFlags |= MDL_IO_SPACE;
|
Mdl->MdlFlags |= MDL_IO_SPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Write the page and move on
|
// Write the page and move on
|
||||||
//
|
//
|
||||||
*MdlPages++ = PageFrameIndex;
|
*MdlPages++ = PageFrameIndex;
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
|
|
||||||
/* Check if we're on a PDE boundary */
|
/* Check if we're on a PDE boundary */
|
||||||
if (!((ULONG_PTR)PointerPte & (PD_SIZE - 1))) PointerPde++;
|
if (!((ULONG_PTR)PointerPte & (PD_SIZE - 1))) PointerPde++;
|
||||||
} while (PointerPte <= LastPte);
|
} while (PointerPte <= LastPte);
|
||||||
|
|
||||||
//
|
//
|
||||||
// What kind of lock where we using?
|
// What kind of lock where we using?
|
||||||
//
|
//
|
||||||
|
@ -1055,19 +1054,19 @@ MmProbeAndLockPages(IN PMDL Mdl,
|
||||||
/* Release process working set */
|
/* Release process working set */
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
MiUnlockProcessWorkingSet(CurrentProcess, PsGetCurrentThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity check
|
// Sanity check
|
||||||
//
|
//
|
||||||
ASSERT((Mdl->MdlFlags & MDL_DESCRIBES_AWE) == 0);
|
ASSERT((Mdl->MdlFlags & MDL_DESCRIBES_AWE) == 0);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CleanupWithLock:
|
CleanupWithLock:
|
||||||
//
|
//
|
||||||
// This is the failure path
|
// This is the failure path
|
||||||
//
|
//
|
||||||
ASSERT(!NT_SUCCESS(Status));
|
ASSERT(!NT_SUCCESS(Status));
|
||||||
|
|
||||||
//
|
//
|
||||||
// What kind of lock where we using?
|
// What kind of lock where we using?
|
||||||
//
|
//
|
||||||
|
@ -1089,7 +1088,7 @@ Cleanup:
|
||||||
//
|
//
|
||||||
ASSERT(Mdl->MdlFlags & MDL_PAGES_LOCKED);
|
ASSERT(Mdl->MdlFlags & MDL_PAGES_LOCKED);
|
||||||
MmUnlockPages(Mdl);
|
MmUnlockPages(Mdl);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Raise the error
|
// Raise the error
|
||||||
//
|
//
|
||||||
|
@ -1111,7 +1110,7 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
USHORT RefCount, OldRefCount;
|
USHORT RefCount, OldRefCount;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
DPRINT("Unlocking MDL: %p\n", Mdl);
|
DPRINT("Unlocking MDL: %p\n", Mdl);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
//
|
//
|
||||||
|
@ -1119,13 +1118,13 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
ASSERT((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0);
|
ASSERT((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0);
|
||||||
ASSERT((Mdl->MdlFlags & MDL_PARTIAL) == 0);
|
ASSERT((Mdl->MdlFlags & MDL_PARTIAL) == 0);
|
||||||
ASSERT(Mdl->ByteCount != 0);
|
ASSERT(Mdl->ByteCount != 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the process associated and capture the flags which are volatile
|
// Get the process associated and capture the flags which are volatile
|
||||||
//
|
//
|
||||||
Process = Mdl->Process;
|
Process = Mdl->Process;
|
||||||
Flags = Mdl->MdlFlags;
|
Flags = Mdl->MdlFlags;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Automagically undo any calls to MmGetSystemAddressForMdl's for this MDL
|
// Automagically undo any calls to MmGetSystemAddressForMdl's for this MDL
|
||||||
//
|
//
|
||||||
|
@ -1136,7 +1135,7 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
//
|
//
|
||||||
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
|
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the page count
|
// Get the page count
|
||||||
//
|
//
|
||||||
|
@ -1144,22 +1143,22 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
Base = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset);
|
Base = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset);
|
||||||
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base, Mdl->ByteCount);
|
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base, Mdl->ByteCount);
|
||||||
ASSERT(PageCount != 0);
|
ASSERT(PageCount != 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// We don't support AWE
|
// We don't support AWE
|
||||||
//
|
//
|
||||||
if (Flags & MDL_DESCRIBES_AWE) ASSERT(FALSE);
|
if (Flags & MDL_DESCRIBES_AWE) ASSERT(FALSE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if the buffer is mapped I/O space
|
// Check if the buffer is mapped I/O space
|
||||||
//
|
//
|
||||||
if (Flags & MDL_IO_SPACE)
|
if (Flags & MDL_IO_SPACE)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Acquire PFN lock
|
// Acquire PFN lock
|
||||||
//
|
//
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop every page
|
// Loop every page
|
||||||
//
|
//
|
||||||
|
@ -1170,7 +1169,7 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
// Last page, break out
|
// Last page, break out
|
||||||
//
|
//
|
||||||
if (*MdlPages == LIST_HEAD) break;
|
if (*MdlPages == LIST_HEAD) break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this page is in the PFN database
|
// Check if this page is in the PFN database
|
||||||
//
|
//
|
||||||
|
@ -1188,14 +1187,14 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
|
||||||
ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
|
ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
|
||||||
ASSERT(Pfn1->u2.ShareCount == 0);
|
ASSERT(Pfn1->u2.ShareCount == 0);
|
||||||
|
|
||||||
/* Not supported yet */
|
/* Not supported yet */
|
||||||
ASSERT(((Pfn1->u3.e1.PrototypePte == 0) &&
|
ASSERT(((Pfn1->u3.e1.PrototypePte == 0) &&
|
||||||
(Pfn1->OriginalPte.u.Soft.Prototype == 0)));
|
(Pfn1->OriginalPte.u.Soft.Prototype == 0)));
|
||||||
|
|
||||||
/* One less page */
|
/* One less page */
|
||||||
InterlockedExchangeAddSizeT(&MmSystemLockPagesCount, -1);
|
InterlockedExchangeAddSizeT(&MmSystemLockPagesCount, -1);
|
||||||
|
|
||||||
/* Do the last dereference, we're done here */
|
/* Do the last dereference, we're done here */
|
||||||
MiDecrementReferenceCount(Pfn1, *MdlPages);
|
MiDecrementReferenceCount(Pfn1, *MdlPages);
|
||||||
}
|
}
|
||||||
|
@ -1236,12 +1235,12 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (++MdlPages < LastPage);
|
} while (++MdlPages < LastPage);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the lock
|
// Release the lock
|
||||||
//
|
//
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we have a process
|
// Check if we have a process
|
||||||
//
|
//
|
||||||
|
@ -1254,7 +1253,7 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
InterlockedExchangeAddSizeT(&Process->NumberOfLockedPages,
|
InterlockedExchangeAddSizeT(&Process->NumberOfLockedPages,
|
||||||
-PageCount);
|
-PageCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// We're done
|
// We're done
|
||||||
//
|
//
|
||||||
|
@ -1262,7 +1261,7 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
Mdl->MdlFlags &= ~MDL_PAGES_LOCKED;
|
Mdl->MdlFlags &= ~MDL_PAGES_LOCKED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we have a process
|
// Check if we have a process
|
||||||
//
|
//
|
||||||
|
@ -1275,7 +1274,7 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
InterlockedExchangeAddSizeT(&Process->NumberOfLockedPages,
|
InterlockedExchangeAddSizeT(&Process->NumberOfLockedPages,
|
||||||
-PageCount);
|
-PageCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop every page
|
// Loop every page
|
||||||
//
|
//
|
||||||
|
@ -1298,24 +1297,24 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
Mdl->MdlFlags &= ~MDL_PAGES_LOCKED;
|
Mdl->MdlFlags &= ~MDL_PAGES_LOCKED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Otherwise, stop here
|
// Otherwise, stop here
|
||||||
//
|
//
|
||||||
LastPage = MdlPages;
|
LastPage = MdlPages;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the PFN entry instead for the secondary loop */
|
/* Save the PFN entry instead for the secondary loop */
|
||||||
*MdlPages = (PFN_NUMBER)MiGetPfnEntry(*MdlPages);
|
*MdlPages = (PFN_NUMBER)MiGetPfnEntry(*MdlPages);
|
||||||
ASSERT((*MdlPages) != 0);
|
ASSERT((*MdlPages) != 0);
|
||||||
} while (++MdlPages < LastPage);
|
} while (++MdlPages < LastPage);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reset pointer
|
// Reset pointer
|
||||||
//
|
//
|
||||||
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now grab the PFN lock for the actual unlock and dereference
|
// Now grab the PFN lock for the actual unlock and dereference
|
||||||
//
|
//
|
||||||
|
@ -1334,14 +1333,14 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
|
||||||
ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
|
ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
|
||||||
ASSERT(Pfn1->u2.ShareCount == 0);
|
ASSERT(Pfn1->u2.ShareCount == 0);
|
||||||
|
|
||||||
/* Not supported yet */
|
/* Not supported yet */
|
||||||
ASSERT(((Pfn1->u3.e1.PrototypePte == 0) &&
|
ASSERT(((Pfn1->u3.e1.PrototypePte == 0) &&
|
||||||
(Pfn1->OriginalPte.u.Soft.Prototype == 0)));
|
(Pfn1->OriginalPte.u.Soft.Prototype == 0)));
|
||||||
|
|
||||||
/* One less page */
|
/* One less page */
|
||||||
InterlockedExchangeAddSizeT(&MmSystemLockPagesCount, -1);
|
InterlockedExchangeAddSizeT(&MmSystemLockPagesCount, -1);
|
||||||
|
|
||||||
/* Do the last dereference, we're done here */
|
/* Do the last dereference, we're done here */
|
||||||
MiDecrementReferenceCount(Pfn1, MiGetPfnEntryIndex(Pfn1));
|
MiDecrementReferenceCount(Pfn1, MiGetPfnEntryIndex(Pfn1));
|
||||||
}
|
}
|
||||||
|
@ -1381,12 +1380,12 @@ MmUnlockPages(IN PMDL Mdl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (++MdlPages < LastPage);
|
} while (++MdlPages < LastPage);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the lock
|
// Release the lock
|
||||||
//
|
//
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
//
|
//
|
||||||
// We're done
|
// We're done
|
||||||
//
|
//
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 16 "ARM³::DEBUGSUP"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -47,7 +46,7 @@ MiDbgTranslatePhysicalAddress(IN ULONG64 PhysicalAddress,
|
||||||
PVOID MappingBaseAddress;
|
PVOID MappingBaseAddress;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we are called too early
|
// Check if we are called too early
|
||||||
//
|
//
|
||||||
if (MmDebugPte == NULL)
|
if (MmDebugPte == NULL)
|
||||||
{
|
{
|
||||||
|
@ -133,7 +132,7 @@ MiDbgUnTranslatePhysicalAddress(VOID)
|
||||||
//
|
//
|
||||||
ASSERT(MmIsAddressValid(MappingBaseAddress));
|
ASSERT(MmIsAddressValid(MappingBaseAddress));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Clear the mapping PTE and invalidate its TLB entry
|
// Clear the mapping PTE and invalidate its TLB entry
|
||||||
//
|
//
|
||||||
MmDebugPte->u.Long = 0;
|
MmDebugPte->u.Long = 0;
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::INIT"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "miarm.h"
|
#include "miarm.h"
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@ PFN_NUMBER MmMaximumNonPagedPoolInPages;
|
||||||
//
|
//
|
||||||
SIZE_T MmMinimumNonPagedPoolSize = 256 * 1024;
|
SIZE_T MmMinimumNonPagedPoolSize = 256 * 1024;
|
||||||
ULONG MmMinAdditionNonPagedPoolPerMb = 32 * 1024;
|
ULONG MmMinAdditionNonPagedPoolPerMb = 32 * 1024;
|
||||||
SIZE_T MmDefaultMaximumNonPagedPool = 1024 * 1024;
|
SIZE_T MmDefaultMaximumNonPagedPool = 1024 * 1024;
|
||||||
ULONG MmMaxAdditionNonPagedPoolPerMb = 400 * 1024;
|
ULONG MmMaxAdditionNonPagedPoolPerMb = 400 * 1024;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -58,7 +57,7 @@ ULONG MmMaxAdditionNonPagedPoolPerMb = 400 * 1024;
|
||||||
// Right now we call this the "ARM³ Nonpaged Pool" and it begins somewhere after
|
// Right now we call this the "ARM³ Nonpaged Pool" and it begins somewhere after
|
||||||
// the PFN database (which starts at 0xB0000000).
|
// the PFN database (which starts at 0xB0000000).
|
||||||
//
|
//
|
||||||
// The expansion nonpaged pool, on the other hand, can grow much bigger (400MB
|
// The expansion nonpaged pool, on the other hand, can grow much bigger (400MB
|
||||||
// for a 1GB system). On ARM³ however, it is currently capped at 128MB.
|
// for a 1GB system). On ARM³ however, it is currently capped at 128MB.
|
||||||
//
|
//
|
||||||
// The address where the initial nonpaged pool starts is aptly named
|
// The address where the initial nonpaged pool starts is aptly named
|
||||||
|
@ -78,7 +77,7 @@ ULONG MmMaxAdditionNonPagedPoolPerMb = 400 * 1024;
|
||||||
// a System PTE, it is always valid, until the System PTE is torn down.
|
// a System PTE, it is always valid, until the System PTE is torn down.
|
||||||
//
|
//
|
||||||
// System PTEs are actually composed of two "spaces", the system space proper,
|
// System PTEs are actually composed of two "spaces", the system space proper,
|
||||||
// and the nonpaged pool expansion space. The latter, as we've already seen,
|
// and the nonpaged pool expansion space. The latter, as we've already seen,
|
||||||
// begins at MmNonPagedPoolExpansionStart. Based on the number of System PTEs
|
// begins at MmNonPagedPoolExpansionStart. Based on the number of System PTEs
|
||||||
// that the system will support, the remaining address space below this address
|
// that the system will support, the remaining address space below this address
|
||||||
// is used to hold the system space PTEs. This address, in turn, is held in the
|
// is used to hold the system space PTEs. This address, in turn, is held in the
|
||||||
|
@ -116,7 +115,7 @@ PFN_NUMBER MmSizeOfPagedPoolInPages = MI_MIN_INIT_PAGED_POOLSIZE / PAGE_SIZE;
|
||||||
// drivers, followed by a 4MB area containing the session's working set. This is
|
// drivers, followed by a 4MB area containing the session's working set. This is
|
||||||
// then followed by a 20MB mapped view area and finally by the session's paged
|
// then followed by a 20MB mapped view area and finally by the session's paged
|
||||||
// pool, by default 16MB.
|
// pool, by default 16MB.
|
||||||
//
|
//
|
||||||
// On a normal system, this results in session space occupying the region from
|
// On a normal system, this results in session space occupying the region from
|
||||||
// 0xBD000000 to 0xC0000000
|
// 0xBD000000 to 0xC0000000
|
||||||
//
|
//
|
||||||
|
@ -307,7 +306,7 @@ PFN_NUMBER MiHighNonPagedPoolThreshold;
|
||||||
*/
|
*/
|
||||||
PFN_NUMBER MmMinimumFreePages = 26;
|
PFN_NUMBER MmMinimumFreePages = 26;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This number indicates how many pages we consider to be a low limit of having
|
* This number indicates how many pages we consider to be a low limit of having
|
||||||
* "plenty" of free memory.
|
* "plenty" of free memory.
|
||||||
*
|
*
|
||||||
|
@ -369,7 +368,7 @@ INIT_FUNCTION
|
||||||
MxGetNextPage(IN PFN_NUMBER PageCount)
|
MxGetNextPage(IN PFN_NUMBER PageCount)
|
||||||
{
|
{
|
||||||
PFN_NUMBER Pfn;
|
PFN_NUMBER Pfn;
|
||||||
|
|
||||||
/* Make sure we have enough pages */
|
/* Make sure we have enough pages */
|
||||||
if (PageCount > MxFreeDescriptor->PageCount)
|
if (PageCount > MxFreeDescriptor->PageCount)
|
||||||
{
|
{
|
||||||
|
@ -380,7 +379,7 @@ MxGetNextPage(IN PFN_NUMBER PageCount)
|
||||||
MxOldFreeDescriptor.PageCount,
|
MxOldFreeDescriptor.PageCount,
|
||||||
PageCount);
|
PageCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use our lowest usable free pages */
|
/* Use our lowest usable free pages */
|
||||||
Pfn = MxFreeDescriptor->BasePage;
|
Pfn = MxFreeDescriptor->BasePage;
|
||||||
MxFreeDescriptor->BasePage += PageCount;
|
MxFreeDescriptor->BasePage += PageCount;
|
||||||
|
@ -394,18 +393,18 @@ INIT_FUNCTION
|
||||||
MiComputeColorInformation(VOID)
|
MiComputeColorInformation(VOID)
|
||||||
{
|
{
|
||||||
ULONG L2Associativity;
|
ULONG L2Associativity;
|
||||||
|
|
||||||
/* Check if no setting was provided already */
|
/* Check if no setting was provided already */
|
||||||
if (!MmSecondaryColors)
|
if (!MmSecondaryColors)
|
||||||
{
|
{
|
||||||
/* Get L2 cache information */
|
/* Get L2 cache information */
|
||||||
L2Associativity = KeGetPcr()->SecondLevelCacheAssociativity;
|
L2Associativity = KeGetPcr()->SecondLevelCacheAssociativity;
|
||||||
|
|
||||||
/* The number of colors is the number of cache bytes by set/way */
|
/* The number of colors is the number of cache bytes by set/way */
|
||||||
MmSecondaryColors = KeGetPcr()->SecondLevelCacheSize;
|
MmSecondaryColors = KeGetPcr()->SecondLevelCacheSize;
|
||||||
if (L2Associativity) MmSecondaryColors /= L2Associativity;
|
if (L2Associativity) MmSecondaryColors /= L2Associativity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now convert cache bytes into pages */
|
/* Now convert cache bytes into pages */
|
||||||
MmSecondaryColors >>= PAGE_SHIFT;
|
MmSecondaryColors >>= PAGE_SHIFT;
|
||||||
if (!MmSecondaryColors)
|
if (!MmSecondaryColors)
|
||||||
|
@ -421,14 +420,14 @@ MiComputeColorInformation(VOID)
|
||||||
/* Set the maximum */
|
/* Set the maximum */
|
||||||
MmSecondaryColors = MI_MAX_SECONDARY_COLORS;
|
MmSecondaryColors = MI_MAX_SECONDARY_COLORS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure there aren't too little colors */
|
/* Make sure there aren't too little colors */
|
||||||
if (MmSecondaryColors < MI_MIN_SECONDARY_COLORS)
|
if (MmSecondaryColors < MI_MIN_SECONDARY_COLORS)
|
||||||
{
|
{
|
||||||
/* Set the default */
|
/* Set the default */
|
||||||
MmSecondaryColors = MI_SECONDARY_COLORS;
|
MmSecondaryColors = MI_SECONDARY_COLORS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally make sure the colors are a power of two */
|
/* Finally make sure the colors are a power of two */
|
||||||
if (MmSecondaryColors & (MmSecondaryColors - 1))
|
if (MmSecondaryColors & (MmSecondaryColors - 1))
|
||||||
{
|
{
|
||||||
|
@ -436,10 +435,10 @@ MiComputeColorInformation(VOID)
|
||||||
MmSecondaryColors = MI_SECONDARY_COLORS;
|
MmSecondaryColors = MI_SECONDARY_COLORS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute the mask and store it */
|
/* Compute the mask and store it */
|
||||||
MmSecondaryColorMask = MmSecondaryColors - 1;
|
MmSecondaryColorMask = MmSecondaryColors - 1;
|
||||||
KeGetCurrentPrcb()->SecondaryColorMask = MmSecondaryColorMask;
|
KeGetCurrentPrcb()->SecondaryColorMask = MmSecondaryColorMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -450,10 +449,10 @@ MiInitializeColorTables(VOID)
|
||||||
ULONG i;
|
ULONG i;
|
||||||
PMMPTE PointerPte, LastPte;
|
PMMPTE PointerPte, LastPte;
|
||||||
MMPTE TempPte = ValidKernelPte;
|
MMPTE TempPte = ValidKernelPte;
|
||||||
|
|
||||||
/* The color table starts after the ARM3 PFN database */
|
/* The color table starts after the ARM3 PFN database */
|
||||||
MmFreePagesByColor[0] = (PMMCOLOR_TABLES)&MmPfnDatabase[MmHighestPhysicalPage + 1];
|
MmFreePagesByColor[0] = (PMMCOLOR_TABLES)&MmPfnDatabase[MmHighestPhysicalPage + 1];
|
||||||
|
|
||||||
/* Loop the PTEs. We have two color tables for each secondary color */
|
/* Loop the PTEs. We have two color tables for each secondary color */
|
||||||
PointerPte = MiAddressToPte(&MmFreePagesByColor[0][0]);
|
PointerPte = MiAddressToPte(&MmFreePagesByColor[0][0]);
|
||||||
LastPte = MiAddressToPte((ULONG_PTR)MmFreePagesByColor[0] +
|
LastPte = MiAddressToPte((ULONG_PTR)MmFreePagesByColor[0] +
|
||||||
|
@ -471,14 +470,14 @@ MiInitializeColorTables(VOID)
|
||||||
/* Zero out the page */
|
/* Zero out the page */
|
||||||
RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
|
RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next */
|
/* Next */
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now set the address of the next list, right after this one */
|
/* Now set the address of the next list, right after this one */
|
||||||
MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors];
|
MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors];
|
||||||
|
|
||||||
/* Now loop the lists to set them up */
|
/* Now loop the lists to set them up */
|
||||||
for (i = 0; i < MmSecondaryColors; i++)
|
for (i = 0; i < MmSecondaryColors; i++)
|
||||||
{
|
{
|
||||||
|
@ -561,12 +560,12 @@ MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
||||||
PMMPTE PointerPte, LastPte;
|
PMMPTE PointerPte, LastPte;
|
||||||
MMPTE TempPte = ValidKernelPte;
|
MMPTE TempPte = ValidKernelPte;
|
||||||
|
|
||||||
/* Get current page data, since we won't be using MxGetNextPage as it would corrupt our state */
|
/* Get current page data, since we won't be using MxGetNextPage as it would corrupt our state */
|
||||||
FreePage = MxFreeDescriptor->BasePage;
|
FreePage = MxFreeDescriptor->BasePage;
|
||||||
FreePageCount = MxFreeDescriptor->PageCount;
|
FreePageCount = MxFreeDescriptor->PageCount;
|
||||||
PagesLeft = 0;
|
PagesLeft = 0;
|
||||||
|
|
||||||
/* Loop the memory descriptors */
|
/* Loop the memory descriptors */
|
||||||
NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
|
NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
|
||||||
while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
|
while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
|
||||||
|
@ -583,7 +582,7 @@ MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
NextEntry = MdBlock->ListEntry.Flink;
|
NextEntry = MdBlock->ListEntry.Flink;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next, check if this is our special free descriptor we've found */
|
/* Next, check if this is our special free descriptor we've found */
|
||||||
if (MdBlock == MxFreeDescriptor)
|
if (MdBlock == MxFreeDescriptor)
|
||||||
{
|
{
|
||||||
|
@ -597,12 +596,12 @@ MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
BasePage = MdBlock->BasePage;
|
BasePage = MdBlock->BasePage;
|
||||||
PageCount = MdBlock->PageCount;
|
PageCount = MdBlock->PageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the PTEs for this range */
|
/* Get the PTEs for this range */
|
||||||
PointerPte = MiAddressToPte(&MmPfnDatabase[BasePage]);
|
PointerPte = MiAddressToPte(&MmPfnDatabase[BasePage]);
|
||||||
LastPte = MiAddressToPte(((ULONG_PTR)&MmPfnDatabase[BasePage + PageCount]) - 1);
|
LastPte = MiAddressToPte(((ULONG_PTR)&MmPfnDatabase[BasePage + PageCount]) - 1);
|
||||||
DPRINT("MD Type: %lx Base: %lx Count: %lx\n", MdBlock->MemoryType, BasePage, PageCount);
|
DPRINT("MD Type: %lx Base: %lx Count: %lx\n", MdBlock->MemoryType, BasePage, PageCount);
|
||||||
|
|
||||||
/* Loop them */
|
/* Loop them */
|
||||||
while (PointerPte <= LastPte)
|
while (PointerPte <= LastPte)
|
||||||
{
|
{
|
||||||
|
@ -612,7 +611,7 @@ MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
/* Use the next free page */
|
/* Use the next free page */
|
||||||
TempPte.u.Hard.PageFrameNumber = FreePage;
|
TempPte.u.Hard.PageFrameNumber = FreePage;
|
||||||
ASSERT(FreePageCount != 0);
|
ASSERT(FreePageCount != 0);
|
||||||
|
|
||||||
/* Consume free pages */
|
/* Consume free pages */
|
||||||
FreePage++;
|
FreePage++;
|
||||||
FreePageCount--;
|
FreePageCount--;
|
||||||
|
@ -625,15 +624,15 @@ MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
MxOldFreeDescriptor.PageCount,
|
MxOldFreeDescriptor.PageCount,
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write out this PTE */
|
/* Write out this PTE */
|
||||||
PagesLeft++;
|
PagesLeft++;
|
||||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
|
||||||
/* Zero this page */
|
/* Zero this page */
|
||||||
RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
|
RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next! */
|
/* Next! */
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
}
|
}
|
||||||
|
@ -641,7 +640,7 @@ MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
/* Do the next address range */
|
/* Do the next address range */
|
||||||
NextEntry = MdBlock->ListEntry.Flink;
|
NextEntry = MdBlock->ListEntry.Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now update the free descriptors to consume the pages we used up during the PFN allocation loop */
|
/* Now update the free descriptors to consume the pages we used up during the PFN allocation loop */
|
||||||
MxFreeDescriptor->BasePage = FreePage;
|
MxFreeDescriptor->BasePage = FreePage;
|
||||||
MxFreeDescriptor->PageCount = FreePageCount;
|
MxFreeDescriptor->PageCount = FreePageCount;
|
||||||
|
@ -658,10 +657,10 @@ MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
PFN_NUMBER PageFrameIndex, StartupPdIndex, PtePageIndex;
|
PFN_NUMBER PageFrameIndex, StartupPdIndex, PtePageIndex;
|
||||||
PMMPFN Pfn1, Pfn2;
|
PMMPFN Pfn1, Pfn2;
|
||||||
ULONG_PTR BaseAddress = 0;
|
ULONG_PTR BaseAddress = 0;
|
||||||
|
|
||||||
/* PFN of the startup page directory */
|
/* PFN of the startup page directory */
|
||||||
StartupPdIndex = PFN_FROM_PTE(MiAddressToPde(PDE_BASE));
|
StartupPdIndex = PFN_FROM_PTE(MiAddressToPde(PDE_BASE));
|
||||||
|
|
||||||
/* Start with the first PDE and scan them all */
|
/* Start with the first PDE and scan them all */
|
||||||
PointerPde = MiAddressToPde(NULL);
|
PointerPde = MiAddressToPde(NULL);
|
||||||
Count = PD_COUNT * PDE_COUNT;
|
Count = PD_COUNT * PDE_COUNT;
|
||||||
|
@ -672,7 +671,7 @@ MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
{
|
{
|
||||||
/* Get the PFN from it */
|
/* Get the PFN from it */
|
||||||
PageFrameIndex = PFN_FROM_PTE(PointerPde);
|
PageFrameIndex = PFN_FROM_PTE(PointerPde);
|
||||||
|
|
||||||
/* Do we want a PFN entry for this page? */
|
/* Do we want a PFN entry for this page? */
|
||||||
if (MiIsRegularMemory(LoaderBlock, PageFrameIndex))
|
if (MiIsRegularMemory(LoaderBlock, PageFrameIndex))
|
||||||
{
|
{
|
||||||
|
@ -694,7 +693,7 @@ MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
/* No PFN entry */
|
/* No PFN entry */
|
||||||
Pfn1 = NULL;
|
Pfn1 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now get the PTE and scan the pages */
|
/* Now get the PTE and scan the pages */
|
||||||
PointerPte = MiAddressToPte(BaseAddress);
|
PointerPte = MiAddressToPte(BaseAddress);
|
||||||
for (j = 0; j < PTE_COUNT; j++)
|
for (j = 0; j < PTE_COUNT; j++)
|
||||||
|
@ -705,7 +704,7 @@ MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
/* Increase the shared count of the PFN entry for the PDE */
|
/* Increase the shared count of the PFN entry for the PDE */
|
||||||
ASSERT(Pfn1 != NULL);
|
ASSERT(Pfn1 != NULL);
|
||||||
Pfn1->u2.ShareCount++;
|
Pfn1->u2.ShareCount++;
|
||||||
|
|
||||||
/* Now check if the PTE is valid memory too */
|
/* Now check if the PTE is valid memory too */
|
||||||
PtePageIndex = PFN_FROM_PTE(PointerPte);
|
PtePageIndex = PFN_FROM_PTE(PointerPte);
|
||||||
if (MiIsRegularMemory(LoaderBlock, PtePageIndex))
|
if (MiIsRegularMemory(LoaderBlock, PtePageIndex))
|
||||||
|
@ -739,7 +738,7 @@ MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next PTE */
|
/* Next PTE */
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
BaseAddress += PAGE_SIZE;
|
BaseAddress += PAGE_SIZE;
|
||||||
|
@ -750,7 +749,7 @@ MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
/* Next PDE mapped address */
|
/* Next PDE mapped address */
|
||||||
BaseAddress += PDE_MAPPED_VA;
|
BaseAddress += PDE_MAPPED_VA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next PTE */
|
/* Next PTE */
|
||||||
PointerPde++;
|
PointerPde++;
|
||||||
}
|
}
|
||||||
|
@ -763,7 +762,7 @@ MiBuildPfnDatabaseZeroPage(VOID)
|
||||||
{
|
{
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
PMMPDE PointerPde;
|
PMMPDE PointerPde;
|
||||||
|
|
||||||
/* Grab the lowest page and check if it has no real references */
|
/* Grab the lowest page and check if it has no real references */
|
||||||
Pfn1 = MiGetPfnEntry(MmLowestPhysicalPage);
|
Pfn1 = MiGetPfnEntry(MmLowestPhysicalPage);
|
||||||
if (!(MmLowestPhysicalPage) && !(Pfn1->u3.e2.ReferenceCount))
|
if (!(MmLowestPhysicalPage) && !(Pfn1->u3.e2.ReferenceCount))
|
||||||
|
@ -776,7 +775,7 @@ MiBuildPfnDatabaseZeroPage(VOID)
|
||||||
Pfn1->u3.e2.ReferenceCount = 0xFFF0;
|
Pfn1->u3.e2.ReferenceCount = 0xFFF0;
|
||||||
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
||||||
Pfn1->u3.e1.CacheAttribute = MiNonCached;
|
Pfn1->u3.e1.CacheAttribute = MiNonCached;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -792,7 +791,7 @@ MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
PMMPTE PointerPte;
|
PMMPTE PointerPte;
|
||||||
PMMPDE PointerPde;
|
PMMPDE PointerPde;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
|
||||||
/* Now loop through the descriptors */
|
/* Now loop through the descriptors */
|
||||||
NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
|
NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
|
||||||
while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
|
while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
|
||||||
|
@ -819,7 +818,7 @@ MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
/* In which case we'll trim the descriptor to go as high as we can */
|
/* In which case we'll trim the descriptor to go as high as we can */
|
||||||
PageCount = MmHighestPhysicalPage + 1 - PageFrameIndex;
|
PageCount = MmHighestPhysicalPage + 1 - PageFrameIndex;
|
||||||
MdBlock->PageCount = PageCount;
|
MdBlock->PageCount = PageCount;
|
||||||
|
|
||||||
/* But if there's nothing left to trim, we got too high, so quit */
|
/* But if there's nothing left to trim, we got too high, so quit */
|
||||||
if (!PageCount) break;
|
if (!PageCount) break;
|
||||||
}
|
}
|
||||||
|
@ -829,7 +828,7 @@ MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
{
|
{
|
||||||
/* Check for bad RAM */
|
/* Check for bad RAM */
|
||||||
case LoaderBad:
|
case LoaderBad:
|
||||||
|
|
||||||
DPRINT1("You either have specified /BURNMEMORY or damaged RAM modules.\n");
|
DPRINT1("You either have specified /BURNMEMORY or damaged RAM modules.\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -842,7 +841,7 @@ MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
/* Get the last page of this descriptor. Note we loop backwards */
|
/* Get the last page of this descriptor. Note we loop backwards */
|
||||||
PageFrameIndex += PageCount - 1;
|
PageFrameIndex += PageCount - 1;
|
||||||
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
||||||
|
|
||||||
/* Lock the PFN Database */
|
/* Lock the PFN Database */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
while (PageCount--)
|
while (PageCount--)
|
||||||
|
@ -859,10 +858,10 @@ MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
Pfn1--;
|
Pfn1--;
|
||||||
PageFrameIndex--;
|
PageFrameIndex--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release PFN database */
|
/* Release PFN database */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
/* Done with this block */
|
/* Done with this block */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -895,7 +894,7 @@ MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
#if MI_TRACE_PFNS
|
#if MI_TRACE_PFNS
|
||||||
Pfn1->PfnUsage = MI_USAGE_BOOT_DRIVER;
|
Pfn1->PfnUsage = MI_USAGE_BOOT_DRIVER;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check for RAM disk page */
|
/* Check for RAM disk page */
|
||||||
if (MdBlock->MemoryType == LoaderXIPRom)
|
if (MdBlock->MemoryType == LoaderXIPRom)
|
||||||
{
|
{
|
||||||
|
@ -909,7 +908,7 @@ MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
Pfn1->u3.e1.PrototypePte = 1;
|
Pfn1->u3.e1.PrototypePte = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Advance page structures */
|
/* Advance page structures */
|
||||||
Pfn1++;
|
Pfn1++;
|
||||||
PageFrameIndex++;
|
PageFrameIndex++;
|
||||||
|
@ -930,7 +929,7 @@ MiBuildPfnDatabaseSelf(VOID)
|
||||||
{
|
{
|
||||||
PMMPTE PointerPte, LastPte;
|
PMMPTE PointerPte, LastPte;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
|
|
||||||
/* Loop the PFN database page */
|
/* Loop the PFN database page */
|
||||||
PointerPte = MiAddressToPte(MiGetPfnEntry(MmLowestPhysicalPage));
|
PointerPte = MiAddressToPte(MiGetPfnEntry(MmLowestPhysicalPage));
|
||||||
LastPte = MiAddressToPte(MiGetPfnEntry(MmHighestPhysicalPage));
|
LastPte = MiAddressToPte(MiGetPfnEntry(MmHighestPhysicalPage));
|
||||||
|
@ -947,7 +946,7 @@ MiBuildPfnDatabaseSelf(VOID)
|
||||||
Pfn1->PfnUsage = MI_USAGE_PFN_DATABASE;
|
Pfn1->PfnUsage = MI_USAGE_PFN_DATABASE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next */
|
/* Next */
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
}
|
}
|
||||||
|
@ -960,14 +959,14 @@ MiInitializePfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
{
|
{
|
||||||
/* Scan memory and start setting up PFN entries */
|
/* Scan memory and start setting up PFN entries */
|
||||||
MiBuildPfnDatabaseFromPages(LoaderBlock);
|
MiBuildPfnDatabaseFromPages(LoaderBlock);
|
||||||
|
|
||||||
/* Add the zero page */
|
/* Add the zero page */
|
||||||
MiBuildPfnDatabaseZeroPage();
|
MiBuildPfnDatabaseZeroPage();
|
||||||
|
|
||||||
/* Scan the loader block and build the rest of the PFN database */
|
/* Scan the loader block and build the rest of the PFN database */
|
||||||
MiBuildPfnDatabaseFromLoaderBlock(LoaderBlock);
|
MiBuildPfnDatabaseFromLoaderBlock(LoaderBlock);
|
||||||
|
|
||||||
/* Finally add the pages for the PFN database itself */
|
/* Finally add the pages for the PFN database itself */
|
||||||
MiBuildPfnDatabaseSelf();
|
MiBuildPfnDatabaseSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,7 +976,7 @@ INIT_FUNCTION
|
||||||
MiAdjustWorkingSetManagerParameters(IN BOOLEAN Client)
|
MiAdjustWorkingSetManagerParameters(IN BOOLEAN Client)
|
||||||
{
|
{
|
||||||
/* This function needs to do more work, for now, we tune page minimums */
|
/* This function needs to do more work, for now, we tune page minimums */
|
||||||
|
|
||||||
/* Check for a system with around 64MB RAM or more */
|
/* Check for a system with around 64MB RAM or more */
|
||||||
if (MmNumberOfPhysicalPages >= (63 * _1MB) / PAGE_SIZE)
|
if (MmNumberOfPhysicalPages >= (63 * _1MB) / PAGE_SIZE)
|
||||||
{
|
{
|
||||||
|
@ -1044,35 +1043,35 @@ MiCreateMemoryEvent(IN PUNICODE_STRING Name,
|
||||||
/* Setup the ACL inside it */
|
/* Setup the ACL inside it */
|
||||||
Status = RtlCreateAcl(Dacl, DaclLength, ACL_REVISION);
|
Status = RtlCreateAcl(Dacl, DaclLength, ACL_REVISION);
|
||||||
if (!NT_SUCCESS(Status)) goto CleanUp;
|
if (!NT_SUCCESS(Status)) goto CleanUp;
|
||||||
|
|
||||||
/* Add query rights for everyone */
|
/* Add query rights for everyone */
|
||||||
Status = RtlAddAccessAllowedAce(Dacl,
|
Status = RtlAddAccessAllowedAce(Dacl,
|
||||||
ACL_REVISION,
|
ACL_REVISION,
|
||||||
SYNCHRONIZE | EVENT_QUERY_STATE | READ_CONTROL,
|
SYNCHRONIZE | EVENT_QUERY_STATE | READ_CONTROL,
|
||||||
SeWorldSid);
|
SeWorldSid);
|
||||||
if (!NT_SUCCESS(Status)) goto CleanUp;
|
if (!NT_SUCCESS(Status)) goto CleanUp;
|
||||||
|
|
||||||
/* Full rights for the admin */
|
/* Full rights for the admin */
|
||||||
Status = RtlAddAccessAllowedAce(Dacl,
|
Status = RtlAddAccessAllowedAce(Dacl,
|
||||||
ACL_REVISION,
|
ACL_REVISION,
|
||||||
EVENT_ALL_ACCESS,
|
EVENT_ALL_ACCESS,
|
||||||
SeAliasAdminsSid);
|
SeAliasAdminsSid);
|
||||||
if (!NT_SUCCESS(Status)) goto CleanUp;
|
if (!NT_SUCCESS(Status)) goto CleanUp;
|
||||||
|
|
||||||
/* As well as full rights for the system */
|
/* As well as full rights for the system */
|
||||||
Status = RtlAddAccessAllowedAce(Dacl,
|
Status = RtlAddAccessAllowedAce(Dacl,
|
||||||
ACL_REVISION,
|
ACL_REVISION,
|
||||||
EVENT_ALL_ACCESS,
|
EVENT_ALL_ACCESS,
|
||||||
SeLocalSystemSid);
|
SeLocalSystemSid);
|
||||||
if (!NT_SUCCESS(Status)) goto CleanUp;
|
if (!NT_SUCCESS(Status)) goto CleanUp;
|
||||||
|
|
||||||
/* Set this DACL inside the SD */
|
/* Set this DACL inside the SD */
|
||||||
Status = RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
|
Status = RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
|
||||||
TRUE,
|
TRUE,
|
||||||
Dacl,
|
Dacl,
|
||||||
FALSE);
|
FALSE);
|
||||||
if (!NT_SUCCESS(Status)) goto CleanUp;
|
if (!NT_SUCCESS(Status)) goto CleanUp;
|
||||||
|
|
||||||
/* Setup the event attributes, making sure it's a permanent one */
|
/* Setup the event attributes, making sure it's a permanent one */
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
Name,
|
Name,
|
||||||
|
@ -1100,7 +1099,7 @@ CleanUp:
|
||||||
KernelMode,
|
KernelMode,
|
||||||
(PVOID*)Event,
|
(PVOID*)Event,
|
||||||
NULL);
|
NULL);
|
||||||
ZwClose (EventHandle);
|
ZwClose (EventHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return status */
|
/* Return status */
|
||||||
|
@ -1297,30 +1296,30 @@ MmDumpArmPfnDatabase(IN BOOLEAN StatusOnly)
|
||||||
switch (Pfn1->u3.e1.PageLocation)
|
switch (Pfn1->u3.e1.PageLocation)
|
||||||
{
|
{
|
||||||
case ActiveAndValid:
|
case ActiveAndValid:
|
||||||
|
|
||||||
Consumer = "Active and Valid";
|
Consumer = "Active and Valid";
|
||||||
ActivePages++;
|
ActivePages++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZeroedPageList:
|
case ZeroedPageList:
|
||||||
|
|
||||||
Consumer = "Zero Page List";
|
Consumer = "Zero Page List";
|
||||||
FreePages++;
|
FreePages++;
|
||||||
break;//continue;
|
break;//continue;
|
||||||
|
|
||||||
case FreePageList:
|
case FreePageList:
|
||||||
|
|
||||||
Consumer = "Free Page List";
|
Consumer = "Free Page List";
|
||||||
FreePages++;
|
FreePages++;
|
||||||
break;//continue;
|
break;//continue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
Consumer = "Other (ASSERT!)";
|
Consumer = "Other (ASSERT!)";
|
||||||
OtherPages++;
|
OtherPages++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MI_TRACE_PFNS
|
#if MI_TRACE_PFNS
|
||||||
/* Add into bucket */
|
/* Add into bucket */
|
||||||
UsageBucket[Pfn1->PfnUsage]++;
|
UsageBucket[Pfn1->PfnUsage]++;
|
||||||
|
@ -1343,7 +1342,7 @@ MmDumpArmPfnDatabase(IN BOOLEAN StatusOnly)
|
||||||
"is disabled");
|
"is disabled");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgPrint("Active: %5d pages\t[%6d KB]\n", ActivePages, (ActivePages << PAGE_SHIFT) / 1024);
|
DbgPrint("Active: %5d pages\t[%6d KB]\n", ActivePages, (ActivePages << PAGE_SHIFT) / 1024);
|
||||||
DbgPrint("Free: %5d pages\t[%6d KB]\n", FreePages, (FreePages << PAGE_SHIFT) / 1024);
|
DbgPrint("Free: %5d pages\t[%6d KB]\n", FreePages, (FreePages << PAGE_SHIFT) / 1024);
|
||||||
DbgPrint("-----------------------------------------\n");
|
DbgPrint("-----------------------------------------\n");
|
||||||
|
@ -1380,7 +1379,7 @@ MiPagesInLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
PLIST_ENTRY NextEntry;
|
PLIST_ENTRY NextEntry;
|
||||||
PFN_NUMBER PageCount = 0;
|
PFN_NUMBER PageCount = 0;
|
||||||
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now loop through the descriptors
|
// Now loop through the descriptors
|
||||||
//
|
//
|
||||||
|
@ -1401,13 +1400,13 @@ MiPagesInLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
//
|
//
|
||||||
PageCount += MdBlock->PageCount;
|
PageCount += MdBlock->PageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Try the next descriptor
|
// Try the next descriptor
|
||||||
//
|
//
|
||||||
NextEntry = MdBlock->ListEntry.Flink;
|
NextEntry = MdBlock->ListEntry.Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return the total
|
// Return the total
|
||||||
//
|
//
|
||||||
|
@ -1425,7 +1424,7 @@ MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
PFN_NUMBER NextPage = -1, PageCount = 0;
|
PFN_NUMBER NextPage = -1, PageCount = 0;
|
||||||
PPHYSICAL_MEMORY_DESCRIPTOR Buffer, NewBuffer;
|
PPHYSICAL_MEMORY_DESCRIPTOR Buffer, NewBuffer;
|
||||||
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Scan the memory descriptors
|
// Scan the memory descriptors
|
||||||
//
|
//
|
||||||
|
@ -1438,7 +1437,7 @@ MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
InitialRuns++;
|
InitialRuns++;
|
||||||
NextEntry = NextEntry->Flink;
|
NextEntry = NextEntry->Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate the maximum we'll ever need
|
// Allocate the maximum we'll ever need
|
||||||
//
|
//
|
||||||
|
@ -1453,7 +1452,7 @@ MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
// For now that's how many runs we have
|
// For now that's how many runs we have
|
||||||
//
|
//
|
||||||
Buffer->NumberOfRuns = InitialRuns;
|
Buffer->NumberOfRuns = InitialRuns;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now loop through the descriptors again
|
// Now loop through the descriptors again
|
||||||
//
|
//
|
||||||
|
@ -1473,10 +1472,10 @@ MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
// Add this to our running total
|
// Add this to our running total
|
||||||
//
|
//
|
||||||
PageCount += MdBlock->PageCount;
|
PageCount += MdBlock->PageCount;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if the next page is described by the next descriptor
|
// Check if the next page is described by the next descriptor
|
||||||
//
|
//
|
||||||
if (MdBlock->BasePage == NextPage)
|
if (MdBlock->BasePage == NextPage)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -1494,20 +1493,20 @@ MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
Buffer->Run[Run].BasePage = MdBlock->BasePage;
|
Buffer->Run[Run].BasePage = MdBlock->BasePage;
|
||||||
Buffer->Run[Run].PageCount = MdBlock->PageCount;
|
Buffer->Run[Run].PageCount = MdBlock->PageCount;
|
||||||
NextPage = Buffer->Run[Run].BasePage + Buffer->Run[Run].PageCount;
|
NextPage = Buffer->Run[Run].BasePage + Buffer->Run[Run].PageCount;
|
||||||
|
|
||||||
//
|
//
|
||||||
// And in this case, increase the number of runs
|
// And in this case, increase the number of runs
|
||||||
//
|
//
|
||||||
Run++;
|
Run++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Try the next descriptor
|
// Try the next descriptor
|
||||||
//
|
//
|
||||||
NextEntry = MdBlock->ListEntry.Flink;
|
NextEntry = MdBlock->ListEntry.Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// We should not have been able to go past our initial estimate
|
// We should not have been able to go past our initial estimate
|
||||||
//
|
//
|
||||||
|
@ -1535,14 +1534,14 @@ MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
Buffer->Run,
|
Buffer->Run,
|
||||||
sizeof(PHYSICAL_MEMORY_RUN) * Run);
|
sizeof(PHYSICAL_MEMORY_RUN) * Run);
|
||||||
ExFreePool(Buffer);
|
ExFreePool(Buffer);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now use the new buffer
|
// Now use the new buffer
|
||||||
//
|
//
|
||||||
Buffer = NewBuffer;
|
Buffer = NewBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Write the final numbers, and return it
|
// Write the final numbers, and return it
|
||||||
//
|
//
|
||||||
|
@ -1570,7 +1569,7 @@ MiBuildPagedPool(VOID)
|
||||||
PointerPte = MiAddressToPte(PDE_BASE);
|
PointerPte = MiAddressToPte(PDE_BASE);
|
||||||
ASSERT(PD_COUNT == 1);
|
ASSERT(PD_COUNT == 1);
|
||||||
MmSystemPageDirectory[0] = PFN_FROM_PTE(PointerPte);
|
MmSystemPageDirectory[0] = PFN_FROM_PTE(PointerPte);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate a system PTE which will hold a copy of the page directory
|
// Allocate a system PTE which will hold a copy of the page directory
|
||||||
//
|
//
|
||||||
|
@ -1628,7 +1627,7 @@ MiBuildPagedPool(VOID)
|
||||||
//
|
//
|
||||||
// Let's be really sure this doesn't overflow into nonpaged system VA
|
// Let's be really sure this doesn't overflow into nonpaged system VA
|
||||||
//
|
//
|
||||||
ASSERT((MmSizeOfPagedPoolInBytes + (ULONG_PTR)MmPagedPoolStart) <=
|
ASSERT((MmSizeOfPagedPoolInBytes + (ULONG_PTR)MmPagedPoolStart) <=
|
||||||
(ULONG_PTR)MmNonPagedSystemStart);
|
(ULONG_PTR)MmNonPagedSystemStart);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1641,7 +1640,7 @@ MiBuildPagedPool(VOID)
|
||||||
// So now get the PDE for paged pool and zero it out
|
// So now get the PDE for paged pool and zero it out
|
||||||
//
|
//
|
||||||
PointerPde = MiAddressToPde(MmPagedPoolStart);
|
PointerPde = MiAddressToPde(MmPagedPoolStart);
|
||||||
|
|
||||||
#if (_MI_PAGING_LEVELS >= 3)
|
#if (_MI_PAGING_LEVELS >= 3)
|
||||||
/* On these systems, there's no double-mapping, so instead, the PPE and PXEs
|
/* On these systems, there's no double-mapping, so instead, the PPE and PXEs
|
||||||
* are setup to span the entire paged pool area, so there's no need for the
|
* are setup to span the entire paged pool area, so there's no need for the
|
||||||
|
@ -1759,7 +1758,7 @@ MiBuildPagedPool(VOID)
|
||||||
MiHighPagedPoolThreshold = (60 * _1MB) >> PAGE_SHIFT;
|
MiHighPagedPoolThreshold = (60 * _1MB) >> PAGE_SHIFT;
|
||||||
MiHighPagedPoolThreshold = min(MiHighPagedPoolThreshold, (Size * 2) / 5);
|
MiHighPagedPoolThreshold = min(MiHighPagedPoolThreshold, (Size * 2) / 5);
|
||||||
ASSERT(MiLowPagedPoolThreshold < MiHighPagedPoolThreshold);
|
ASSERT(MiLowPagedPoolThreshold < MiHighPagedPoolThreshold);
|
||||||
|
|
||||||
/* Setup the global session space */
|
/* Setup the global session space */
|
||||||
MiInitializeSystemSpaceMap(NULL);
|
MiInitializeSystemSpaceMap(NULL);
|
||||||
}
|
}
|
||||||
|
@ -1802,7 +1801,7 @@ MiDbgDumpMemoryDescriptors(VOID)
|
||||||
"LoaderReserve ",
|
"LoaderReserve ",
|
||||||
"LoaderXIPRom "
|
"LoaderXIPRom "
|
||||||
};
|
};
|
||||||
|
|
||||||
DPRINT1("Base\t\tLength\t\tType\n");
|
DPRINT1("Base\t\tLength\t\tType\n");
|
||||||
for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
|
for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
|
||||||
NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
|
NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
|
||||||
|
@ -1827,10 +1826,10 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
PVOID Bitmap;
|
PVOID Bitmap;
|
||||||
PPHYSICAL_MEMORY_RUN Run;
|
PPHYSICAL_MEMORY_RUN Run;
|
||||||
PFN_NUMBER PageCount;
|
PFN_NUMBER PageCount;
|
||||||
|
|
||||||
/* Dump memory descriptors */
|
/* Dump memory descriptors */
|
||||||
if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
|
if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Instantiate memory that we don't consider RAM/usable
|
// Instantiate memory that we don't consider RAM/usable
|
||||||
// We use the same exclusions that Windows does, in order to try to be
|
// We use the same exclusions that Windows does, in order to try to be
|
||||||
|
@ -1853,14 +1852,14 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
MiHighPagedPoolEvent = &MiTempEvent;
|
MiHighPagedPoolEvent = &MiTempEvent;
|
||||||
MiLowNonPagedPoolEvent = &MiTempEvent;
|
MiLowNonPagedPoolEvent = &MiTempEvent;
|
||||||
MiHighNonPagedPoolEvent = &MiTempEvent;
|
MiHighNonPagedPoolEvent = &MiTempEvent;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Define the basic user vs. kernel address space separation
|
// Define the basic user vs. kernel address space separation
|
||||||
//
|
//
|
||||||
MmSystemRangeStart = (PVOID)KSEG0_BASE;
|
MmSystemRangeStart = (PVOID)KSEG0_BASE;
|
||||||
MmUserProbeAddress = (ULONG_PTR)MmSystemRangeStart - 0x10000;
|
MmUserProbeAddress = (ULONG_PTR)MmSystemRangeStart - 0x10000;
|
||||||
MmHighestUserAddress = (PVOID)(MmUserProbeAddress - 1);
|
MmHighestUserAddress = (PVOID)(MmUserProbeAddress - 1);
|
||||||
|
|
||||||
/* Highest PTE and PDE based on the addresses above */
|
/* Highest PTE and PDE based on the addresses above */
|
||||||
MiHighestUserPte = MiAddressToPte(MmHighestUserAddress);
|
MiHighestUserPte = MiAddressToPte(MmHighestUserAddress);
|
||||||
MiHighestUserPde = MiAddressToPde(MmHighestUserAddress);
|
MiHighestUserPde = MiAddressToPde(MmHighestUserAddress);
|
||||||
|
@ -1878,7 +1877,7 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
MmBootImageSize *= PAGE_SIZE;
|
MmBootImageSize *= PAGE_SIZE;
|
||||||
MmBootImageSize = (MmBootImageSize + PDE_MAPPED_VA - 1) & ~(PDE_MAPPED_VA - 1);
|
MmBootImageSize = (MmBootImageSize + PDE_MAPPED_VA - 1) & ~(PDE_MAPPED_VA - 1);
|
||||||
ASSERT((MmBootImageSize % PDE_MAPPED_VA) == 0);
|
ASSERT((MmBootImageSize % PDE_MAPPED_VA) == 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set the size of session view, pool, and image
|
// Set the size of session view, pool, and image
|
||||||
//
|
//
|
||||||
|
@ -1886,54 +1885,54 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
MmSessionViewSize = MI_SESSION_VIEW_SIZE;
|
MmSessionViewSize = MI_SESSION_VIEW_SIZE;
|
||||||
MmSessionPoolSize = MI_SESSION_POOL_SIZE;
|
MmSessionPoolSize = MI_SESSION_POOL_SIZE;
|
||||||
MmSessionImageSize = MI_SESSION_IMAGE_SIZE;
|
MmSessionImageSize = MI_SESSION_IMAGE_SIZE;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set the size of system view
|
// Set the size of system view
|
||||||
//
|
//
|
||||||
MmSystemViewSize = MI_SYSTEM_VIEW_SIZE;
|
MmSystemViewSize = MI_SYSTEM_VIEW_SIZE;
|
||||||
|
|
||||||
//
|
//
|
||||||
// This is where it all ends
|
// This is where it all ends
|
||||||
//
|
//
|
||||||
MiSessionImageEnd = (PVOID)PTE_BASE;
|
MiSessionImageEnd = (PVOID)PTE_BASE;
|
||||||
|
|
||||||
//
|
//
|
||||||
// This is where we will load Win32k.sys and the video driver
|
// This is where we will load Win32k.sys and the video driver
|
||||||
//
|
//
|
||||||
MiSessionImageStart = (PVOID)((ULONG_PTR)MiSessionImageEnd -
|
MiSessionImageStart = (PVOID)((ULONG_PTR)MiSessionImageEnd -
|
||||||
MmSessionImageSize);
|
MmSessionImageSize);
|
||||||
|
|
||||||
//
|
//
|
||||||
// So the view starts right below the session working set (itself below
|
// So the view starts right below the session working set (itself below
|
||||||
// the image area)
|
// the image area)
|
||||||
//
|
//
|
||||||
MiSessionViewStart = (PVOID)((ULONG_PTR)MiSessionImageEnd -
|
MiSessionViewStart = (PVOID)((ULONG_PTR)MiSessionImageEnd -
|
||||||
MmSessionImageSize -
|
MmSessionImageSize -
|
||||||
MI_SESSION_WORKING_SET_SIZE -
|
MI_SESSION_WORKING_SET_SIZE -
|
||||||
MmSessionViewSize);
|
MmSessionViewSize);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Session pool follows
|
// Session pool follows
|
||||||
//
|
//
|
||||||
MiSessionPoolEnd = MiSessionViewStart;
|
MiSessionPoolEnd = MiSessionViewStart;
|
||||||
MiSessionPoolStart = (PVOID)((ULONG_PTR)MiSessionPoolEnd -
|
MiSessionPoolStart = (PVOID)((ULONG_PTR)MiSessionPoolEnd -
|
||||||
MmSessionPoolSize);
|
MmSessionPoolSize);
|
||||||
|
|
||||||
//
|
//
|
||||||
// And it all begins here
|
// And it all begins here
|
||||||
//
|
//
|
||||||
MmSessionBase = MiSessionPoolStart;
|
MmSessionBase = MiSessionPoolStart;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity check that our math is correct
|
// Sanity check that our math is correct
|
||||||
//
|
//
|
||||||
ASSERT((ULONG_PTR)MmSessionBase + MmSessionSize == PTE_BASE);
|
ASSERT((ULONG_PTR)MmSessionBase + MmSessionSize == PTE_BASE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Session space ends wherever image session space ends
|
// Session space ends wherever image session space ends
|
||||||
//
|
//
|
||||||
MiSessionSpaceEnd = MiSessionImageEnd;
|
MiSessionSpaceEnd = MiSessionImageEnd;
|
||||||
|
|
||||||
//
|
//
|
||||||
// System view space ends at session space, so now that we know where
|
// System view space ends at session space, so now that we know where
|
||||||
// this is, we can compute the base address of system view space itself.
|
// this is, we can compute the base address of system view space itself.
|
||||||
|
@ -1946,25 +1945,25 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
MiSessionImagePteEnd = MiAddressToPte(MiSessionImageEnd);
|
MiSessionImagePteEnd = MiAddressToPte(MiSessionImageEnd);
|
||||||
MiSessionBasePte = MiAddressToPte(MmSessionBase);
|
MiSessionBasePte = MiAddressToPte(MmSessionBase);
|
||||||
MiSessionLastPte = MiAddressToPte(MiSessionSpaceEnd);
|
MiSessionLastPte = MiAddressToPte(MiSessionSpaceEnd);
|
||||||
|
|
||||||
/* Initialize the user mode image list */
|
/* Initialize the user mode image list */
|
||||||
InitializeListHead(&MmLoadedUserImageList);
|
InitializeListHead(&MmLoadedUserImageList);
|
||||||
|
|
||||||
/* Initialize the paged pool mutex */
|
/* Initialize the paged pool mutex */
|
||||||
KeInitializeGuardedMutex(&MmPagedPoolMutex);
|
KeInitializeGuardedMutex(&MmPagedPoolMutex);
|
||||||
|
|
||||||
/* Initialize the Loader Lock */
|
/* Initialize the Loader Lock */
|
||||||
KeInitializeMutant(&MmSystemLoadLock, FALSE);
|
KeInitializeMutant(&MmSystemLoadLock, FALSE);
|
||||||
|
|
||||||
/* Set the zero page event */
|
/* Set the zero page event */
|
||||||
KeInitializeEvent(&MmZeroingPageEvent, SynchronizationEvent, FALSE);
|
KeInitializeEvent(&MmZeroingPageEvent, SynchronizationEvent, FALSE);
|
||||||
MmZeroingPageThreadActive = FALSE;
|
MmZeroingPageThreadActive = FALSE;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Count physical pages on the system
|
// Count physical pages on the system
|
||||||
//
|
//
|
||||||
PageCount = MiPagesInLoaderBlock(LoaderBlock, IncludeType);
|
PageCount = MiPagesInLoaderBlock(LoaderBlock, IncludeType);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is a machine with less than 19MB of RAM
|
// Check if this is a machine with less than 19MB of RAM
|
||||||
//
|
//
|
||||||
|
@ -1989,17 +1988,17 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
MmNumberOfSystemPtes <<= 1;
|
MmNumberOfSystemPtes <<= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("System PTE count has been tuned to %d (%d bytes)\n",
|
DPRINT("System PTE count has been tuned to %d (%d bytes)\n",
|
||||||
MmNumberOfSystemPtes, MmNumberOfSystemPtes * PAGE_SIZE);
|
MmNumberOfSystemPtes, MmNumberOfSystemPtes * PAGE_SIZE);
|
||||||
|
|
||||||
/* Initialize the working set lock */
|
/* Initialize the working set lock */
|
||||||
ExInitializePushLock((PULONG_PTR)&MmSystemCacheWs.WorkingSetMutex);
|
ExInitializePushLock((PULONG_PTR)&MmSystemCacheWs.WorkingSetMutex);
|
||||||
|
|
||||||
/* Set commit limit */
|
/* Set commit limit */
|
||||||
MmTotalCommitLimit = 2 * _1GB;
|
MmTotalCommitLimit = 2 * _1GB;
|
||||||
MmTotalCommitLimitMaximum = MmTotalCommitLimit;
|
MmTotalCommitLimitMaximum = MmTotalCommitLimit;
|
||||||
|
|
||||||
/* Has the allocation fragment been setup? */
|
/* Has the allocation fragment been setup? */
|
||||||
if (!MmAllocationFragment)
|
if (!MmAllocationFragment)
|
||||||
{
|
{
|
||||||
|
@ -2021,17 +2020,17 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
/* Convert from 1KB fragments to pages */
|
/* Convert from 1KB fragments to pages */
|
||||||
MmAllocationFragment *= _1KB;
|
MmAllocationFragment *= _1KB;
|
||||||
MmAllocationFragment = ROUND_TO_PAGES(MmAllocationFragment);
|
MmAllocationFragment = ROUND_TO_PAGES(MmAllocationFragment);
|
||||||
|
|
||||||
/* Don't let it past the maximum */
|
/* Don't let it past the maximum */
|
||||||
MmAllocationFragment = min(MmAllocationFragment,
|
MmAllocationFragment = min(MmAllocationFragment,
|
||||||
MI_MAX_ALLOCATION_FRAGMENT);
|
MI_MAX_ALLOCATION_FRAGMENT);
|
||||||
|
|
||||||
/* Don't let it too small either */
|
/* Don't let it too small either */
|
||||||
MmAllocationFragment = max(MmAllocationFragment,
|
MmAllocationFragment = max(MmAllocationFragment,
|
||||||
MI_MIN_ALLOCATION_FRAGMENT);
|
MI_MIN_ALLOCATION_FRAGMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the platform-specific parts */
|
/* Initialize the platform-specific parts */
|
||||||
MiInitMachineDependent(LoaderBlock);
|
MiInitMachineDependent(LoaderBlock);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -2039,7 +2038,7 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
//
|
//
|
||||||
MmPhysicalMemoryBlock = MmInitializeMemoryLimits(LoaderBlock,
|
MmPhysicalMemoryBlock = MmInitializeMemoryLimits(LoaderBlock,
|
||||||
IncludeType);
|
IncludeType);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate enough buffer for the PFN bitmap
|
// Allocate enough buffer for the PFN bitmap
|
||||||
// Align it up to a 32-bit boundary
|
// Align it up to a 32-bit boundary
|
||||||
|
@ -2058,7 +2057,7 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
MmHighestPhysicalPage,
|
MmHighestPhysicalPage,
|
||||||
0x101);
|
0x101);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize it and clear all the bits to begin with
|
// Initialize it and clear all the bits to begin with
|
||||||
//
|
//
|
||||||
|
@ -2066,7 +2065,7 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
Bitmap,
|
Bitmap,
|
||||||
MmHighestPhysicalPage + 1);
|
MmHighestPhysicalPage + 1);
|
||||||
RtlClearAllBits(&MiPfnBitMap);
|
RtlClearAllBits(&MiPfnBitMap);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop physical memory runs
|
// Loop physical memory runs
|
||||||
//
|
//
|
||||||
|
@ -2091,7 +2090,7 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
RtlSetBits(&MiPfnBitMap, Run->BasePage, Run->PageCount);
|
RtlSetBits(&MiPfnBitMap, Run->BasePage, Run->PageCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look for large page cache entries that need caching */
|
/* Look for large page cache entries that need caching */
|
||||||
MiSyncCachedRanges();
|
MiSyncCachedRanges();
|
||||||
|
|
||||||
|
@ -2130,7 +2129,7 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
MmSystemSize = MmMediumSystem;
|
MmSystemSize = MmMediumSystem;
|
||||||
MmSystemCacheWsMinimum += 400;
|
MmSystemCacheWsMinimum += 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for less than 24MB */
|
/* Check for less than 24MB */
|
||||||
if (MmNumberOfPhysicalPages < ((24 * _1MB) / PAGE_SIZE))
|
if (MmNumberOfPhysicalPages < ((24 * _1MB) / PAGE_SIZE))
|
||||||
{
|
{
|
||||||
|
@ -2157,14 +2156,14 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for more than 33 MB */
|
/* Check for more than 33 MB */
|
||||||
if (MmNumberOfPhysicalPages > ((33 * _1MB) / PAGE_SIZE))
|
if (MmNumberOfPhysicalPages > ((33 * _1MB) / PAGE_SIZE))
|
||||||
{
|
{
|
||||||
/* Add another 500 pages to the cache */
|
/* Add another 500 pages to the cache */
|
||||||
MmSystemCacheWsMinimum += 500;
|
MmSystemCacheWsMinimum += 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now setup the shared user data fields */
|
/* Now setup the shared user data fields */
|
||||||
ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
|
ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
|
||||||
SharedUserData->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
|
SharedUserData->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
|
||||||
|
@ -2209,25 +2208,25 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
DPRINT1("System cache working set too big\n");
|
DPRINT1("System cache working set too big\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the system cache */
|
/* Initialize the system cache */
|
||||||
//MiInitializeSystemCache(MmSystemCacheWsMinimum, MmAvailablePages);
|
//MiInitializeSystemCache(MmSystemCacheWsMinimum, MmAvailablePages);
|
||||||
|
|
||||||
/* Update the commit limit */
|
/* Update the commit limit */
|
||||||
MmTotalCommitLimit = MmAvailablePages;
|
MmTotalCommitLimit = MmAvailablePages;
|
||||||
if (MmTotalCommitLimit > 1024) MmTotalCommitLimit -= 1024;
|
if (MmTotalCommitLimit > 1024) MmTotalCommitLimit -= 1024;
|
||||||
MmTotalCommitLimitMaximum = MmTotalCommitLimit;
|
MmTotalCommitLimitMaximum = MmTotalCommitLimit;
|
||||||
|
|
||||||
/* Size up paged pool and build the shadow system page directory */
|
/* Size up paged pool and build the shadow system page directory */
|
||||||
MiBuildPagedPool();
|
MiBuildPagedPool();
|
||||||
|
|
||||||
/* Debugger physical memory support is now ready to be used */
|
/* Debugger physical memory support is now ready to be used */
|
||||||
MmDebugPte = MiAddressToPte(MiDebugMapping);
|
MmDebugPte = MiAddressToPte(MiDebugMapping);
|
||||||
|
|
||||||
/* Initialize the loaded module list */
|
/* Initialize the loaded module list */
|
||||||
MiInitializeLoadedModuleList(LoaderBlock);
|
MiInitializeLoadedModuleList(LoaderBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Always return success for now
|
// Always return success for now
|
||||||
//
|
//
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::MMSUP"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -122,7 +121,7 @@ NTAPI
|
||||||
MmIsRecursiveIoFault(VOID)
|
MmIsRecursiveIoFault(VOID)
|
||||||
{
|
{
|
||||||
PETHREAD Thread = PsGetCurrentThread();
|
PETHREAD Thread = PsGetCurrentThread();
|
||||||
|
|
||||||
//
|
//
|
||||||
// If any of these is true, this is a recursive fault
|
// If any of these is true, this is a recursive fault
|
||||||
//
|
//
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::NCACHE"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -29,25 +28,25 @@ MmAllocateNonCachedMemory(IN SIZE_T NumberOfBytes)
|
||||||
PHYSICAL_ADDRESS LowAddress, HighAddress, SkipBytes;
|
PHYSICAL_ADDRESS LowAddress, HighAddress, SkipBytes;
|
||||||
MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
|
MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
|
||||||
PMDL Mdl;
|
PMDL Mdl;
|
||||||
PVOID BaseAddress;
|
PVOID BaseAddress;
|
||||||
PPFN_NUMBER MdlPages;
|
PPFN_NUMBER MdlPages;
|
||||||
PMMPTE PointerPte;
|
PMMPTE PointerPte;
|
||||||
MMPTE TempPte;
|
MMPTE TempPte;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the page count
|
// Get the page count
|
||||||
//
|
//
|
||||||
ASSERT(NumberOfBytes != 0);
|
ASSERT(NumberOfBytes != 0);
|
||||||
PageCount = BYTES_TO_PAGES(NumberOfBytes);
|
PageCount = BYTES_TO_PAGES(NumberOfBytes);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Use the MDL allocator for simplicity, so setup the parameters
|
// Use the MDL allocator for simplicity, so setup the parameters
|
||||||
//
|
//
|
||||||
LowAddress.QuadPart = 0;
|
LowAddress.QuadPart = 0;
|
||||||
HighAddress.QuadPart = -1;
|
HighAddress.QuadPart = -1;
|
||||||
SkipBytes.QuadPart = 0;
|
SkipBytes.QuadPart = 0;
|
||||||
CacheAttribute = MiPlatformCacheAttributes[0][MmNonCached];
|
CacheAttribute = MiPlatformCacheAttributes[0][MmNonCached];
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now call the MDL allocator
|
// Now call the MDL allocator
|
||||||
//
|
//
|
||||||
|
@ -58,7 +57,7 @@ MmAllocateNonCachedMemory(IN SIZE_T NumberOfBytes)
|
||||||
CacheAttribute,
|
CacheAttribute,
|
||||||
0);
|
0);
|
||||||
if (!Mdl) return NULL;
|
if (!Mdl) return NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the MDL VA and check how many pages we got (could be partial)
|
// Get the MDL VA and check how many pages we got (could be partial)
|
||||||
//
|
//
|
||||||
|
@ -74,12 +73,12 @@ MmAllocateNonCachedMemory(IN SIZE_T NumberOfBytes)
|
||||||
ExFreePool(Mdl);
|
ExFreePool(Mdl);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate system PTEs for the base address
|
// Allocate system PTEs for the base address
|
||||||
// We use an extra page to store the actual MDL pointer for the free later
|
// We use an extra page to store the actual MDL pointer for the free later
|
||||||
//
|
//
|
||||||
PointerPte = MiReserveSystemPtes(PageCount + 1, SystemPteSpace);
|
PointerPte = MiReserveSystemPtes(PageCount + 1, SystemPteSpace);
|
||||||
if (!PointerPte)
|
if (!PointerPte)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -89,57 +88,57 @@ MmAllocateNonCachedMemory(IN SIZE_T NumberOfBytes)
|
||||||
ExFreePool(Mdl);
|
ExFreePool(Mdl);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Store the MDL pointer
|
// Store the MDL pointer
|
||||||
//
|
//
|
||||||
*(PMDL*)PointerPte++ = Mdl;
|
*(PMDL*)PointerPte++ = Mdl;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Okay, now see what range we got
|
// Okay, now see what range we got
|
||||||
//
|
//
|
||||||
BaseAddress = MiPteToAddress(PointerPte);
|
BaseAddress = MiPteToAddress(PointerPte);
|
||||||
|
|
||||||
//
|
//
|
||||||
// This is our array of pages
|
// This is our array of pages
|
||||||
//
|
//
|
||||||
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup the template PTE
|
// Setup the template PTE
|
||||||
//
|
//
|
||||||
TempPte = ValidKernelPte;
|
TempPte = ValidKernelPte;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now check what kind of caching we should use
|
// Now check what kind of caching we should use
|
||||||
//
|
//
|
||||||
switch (CacheAttribute)
|
switch (CacheAttribute)
|
||||||
{
|
{
|
||||||
case MiNonCached:
|
case MiNonCached:
|
||||||
|
|
||||||
//
|
//
|
||||||
// Disable caching
|
// Disable caching
|
||||||
//
|
//
|
||||||
MI_PAGE_DISABLE_CACHE(&TempPte);
|
MI_PAGE_DISABLE_CACHE(&TempPte);
|
||||||
MI_PAGE_WRITE_THROUGH(&TempPte);
|
MI_PAGE_WRITE_THROUGH(&TempPte);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MiWriteCombined:
|
case MiWriteCombined:
|
||||||
|
|
||||||
//
|
//
|
||||||
// Enable write combining
|
// Enable write combining
|
||||||
//
|
//
|
||||||
MI_PAGE_DISABLE_CACHE(&TempPte);
|
MI_PAGE_DISABLE_CACHE(&TempPte);
|
||||||
MI_PAGE_WRITE_COMBINED(&TempPte);
|
MI_PAGE_WRITE_COMBINED(&TempPte);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
//
|
//
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
//
|
//
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now loop the MDL pages
|
// Now loop the MDL pages
|
||||||
//
|
//
|
||||||
|
@ -149,19 +148,19 @@ MmAllocateNonCachedMemory(IN SIZE_T NumberOfBytes)
|
||||||
// Get the PFN
|
// Get the PFN
|
||||||
//
|
//
|
||||||
PageFrameIndex = *MdlPages++;
|
PageFrameIndex = *MdlPages++;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set the PFN in the page and write it
|
// Set the PFN in the page and write it
|
||||||
//
|
//
|
||||||
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
||||||
MI_WRITE_VALID_PTE(PointerPte++, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte++, TempPte);
|
||||||
} while (--PageCount);
|
} while (--PageCount);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return the base address
|
// Return the base address
|
||||||
//
|
//
|
||||||
return BaseAddress;
|
return BaseAddress;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -175,34 +174,34 @@ MmFreeNonCachedMemory(IN PVOID BaseAddress,
|
||||||
PMDL Mdl;
|
PMDL Mdl;
|
||||||
PMMPTE PointerPte;
|
PMMPTE PointerPte;
|
||||||
PFN_NUMBER PageCount;
|
PFN_NUMBER PageCount;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
//
|
//
|
||||||
ASSERT(NumberOfBytes != 0);
|
ASSERT(NumberOfBytes != 0);
|
||||||
ASSERT(PAGE_ALIGN(BaseAddress) == BaseAddress);
|
ASSERT(PAGE_ALIGN(BaseAddress) == BaseAddress);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the page count
|
// Get the page count
|
||||||
//
|
//
|
||||||
PageCount = BYTES_TO_PAGES(NumberOfBytes);
|
PageCount = BYTES_TO_PAGES(NumberOfBytes);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the first PTE
|
// Get the first PTE
|
||||||
//
|
//
|
||||||
PointerPte = MiAddressToPte(BaseAddress);
|
PointerPte = MiAddressToPte(BaseAddress);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Remember this is where we store the shadow MDL pointer
|
// Remember this is where we store the shadow MDL pointer
|
||||||
//
|
//
|
||||||
Mdl = *(PMDL*)(--PointerPte);
|
Mdl = *(PMDL*)(--PointerPte);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Kill the MDL (and underlying pages)
|
// Kill the MDL (and underlying pages)
|
||||||
//
|
//
|
||||||
MmFreePagesFromMdl(Mdl);
|
MmFreePagesFromMdl(Mdl);
|
||||||
ExFreePool(Mdl);
|
ExFreePool(Mdl);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now free the system PTEs for the underlying VA
|
// Now free the system PTEs for the underlying VA
|
||||||
//
|
//
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::PAGFAULT"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -32,10 +31,10 @@ MiCheckVirtualAddress(IN PVOID VirtualAddress,
|
||||||
{
|
{
|
||||||
PMMVAD Vad;
|
PMMVAD Vad;
|
||||||
PMMPTE PointerPte;
|
PMMPTE PointerPte;
|
||||||
|
|
||||||
/* No prototype/section support for now */
|
/* No prototype/section support for now */
|
||||||
*ProtoVad = NULL;
|
*ProtoVad = NULL;
|
||||||
|
|
||||||
/* Check if this is a page table address */
|
/* Check if this is a page table address */
|
||||||
if (MI_IS_PAGE_TABLE_ADDRESS(VirtualAddress))
|
if (MI_IS_PAGE_TABLE_ADDRESS(VirtualAddress))
|
||||||
{
|
{
|
||||||
|
@ -47,15 +46,15 @@ MiCheckVirtualAddress(IN PVOID VirtualAddress,
|
||||||
*ProtectCode = MM_NOACCESS;
|
*ProtectCode = MM_NOACCESS;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return full access rights */
|
/* Return full access rights */
|
||||||
*ProtectCode = MM_READWRITE;
|
*ProtectCode = MM_READWRITE;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Should not be a session address */
|
/* Should not be a session address */
|
||||||
ASSERT(MI_IS_SESSION_ADDRESS(VirtualAddress) == FALSE);
|
ASSERT(MI_IS_SESSION_ADDRESS(VirtualAddress) == FALSE);
|
||||||
|
|
||||||
/* Special case for shared data */
|
/* Special case for shared data */
|
||||||
if (PAGE_ALIGN(VirtualAddress) == (PVOID)USER_SHARED_DATA)
|
if (PAGE_ALIGN(VirtualAddress) == (PVOID)USER_SHARED_DATA)
|
||||||
{
|
{
|
||||||
|
@ -63,7 +62,7 @@ MiCheckVirtualAddress(IN PVOID VirtualAddress,
|
||||||
*ProtectCode = MM_READONLY;
|
*ProtectCode = MM_READONLY;
|
||||||
return MmSharedUserDataPte;
|
return MmSharedUserDataPte;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the VAD, it might not exist if the address is bogus */
|
/* Find the VAD, it might not exist if the address is bogus */
|
||||||
Vad = MiLocateAddress(VirtualAddress);
|
Vad = MiLocateAddress(VirtualAddress);
|
||||||
if (!Vad)
|
if (!Vad)
|
||||||
|
@ -75,7 +74,7 @@ MiCheckVirtualAddress(IN PVOID VirtualAddress,
|
||||||
|
|
||||||
/* This must be a VM VAD */
|
/* This must be a VM VAD */
|
||||||
ASSERT(Vad->u.VadFlags.VadType == VadNone);
|
ASSERT(Vad->u.VadFlags.VadType == VadNone);
|
||||||
|
|
||||||
/* Check if it's a section, or just an allocation */
|
/* Check if it's a section, or just an allocation */
|
||||||
if (Vad->u.VadFlags.PrivateMemory == TRUE)
|
if (Vad->u.VadFlags.PrivateMemory == TRUE)
|
||||||
{
|
{
|
||||||
|
@ -89,29 +88,29 @@ MiCheckVirtualAddress(IN PVOID VirtualAddress,
|
||||||
/* Return the proto VAD */
|
/* Return the proto VAD */
|
||||||
ASSERT(Vad->u2.VadFlags2.ExtendableFile == 0);
|
ASSERT(Vad->u2.VadFlags2.ExtendableFile == 0);
|
||||||
*ProtoVad = Vad;
|
*ProtoVad = Vad;
|
||||||
|
|
||||||
/* Get the prototype PTE for this page */
|
/* Get the prototype PTE for this page */
|
||||||
PointerPte = (((ULONG_PTR)VirtualAddress >> PAGE_SHIFT) - Vad->StartingVpn) + Vad->FirstPrototypePte;
|
PointerPte = (((ULONG_PTR)VirtualAddress >> PAGE_SHIFT) - Vad->StartingVpn) + Vad->FirstPrototypePte;
|
||||||
ASSERT(PointerPte <= Vad->LastContiguousPte);
|
ASSERT(PointerPte <= Vad->LastContiguousPte);
|
||||||
ASSERT(PointerPte != NULL);
|
ASSERT(PointerPte != NULL);
|
||||||
|
|
||||||
/* Return the Prototype PTE and the protection for the page mapping */
|
/* Return the Prototype PTE and the protection for the page mapping */
|
||||||
*ProtectCode = Vad->u.VadFlags.Protection;
|
*ProtectCode = Vad->u.VadFlags.Protection;
|
||||||
return PointerPte;
|
return PointerPte;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
FASTCALL
|
FASTCALL
|
||||||
MiCheckPdeForPagedPool(IN PVOID Address)
|
MiCheckPdeForPagedPool(IN PVOID Address)
|
||||||
{
|
{
|
||||||
PMMPDE PointerPde;
|
PMMPDE PointerPde;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
/* No session support in ReactOS yet */
|
/* No session support in ReactOS yet */
|
||||||
ASSERT(MI_IS_SESSION_ADDRESS(Address) == FALSE);
|
ASSERT(MI_IS_SESSION_ADDRESS(Address) == FALSE);
|
||||||
ASSERT(MI_IS_SESSION_PTE(Address) == FALSE);
|
ASSERT(MI_IS_SESSION_PTE(Address) == FALSE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is a fault while trying to access the page table itself
|
// Check if this is a fault while trying to access the page table itself
|
||||||
//
|
//
|
||||||
|
@ -129,7 +128,7 @@ MiCheckPdeForPagedPool(IN PVOID Address)
|
||||||
//
|
//
|
||||||
// This is totally illegal
|
// This is totally illegal
|
||||||
//
|
//
|
||||||
return STATUS_ACCESS_VIOLATION;
|
return STATUS_ACCESS_VIOLATION;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -138,7 +137,7 @@ MiCheckPdeForPagedPool(IN PVOID Address)
|
||||||
//
|
//
|
||||||
PointerPde = MiAddressToPde(Address);
|
PointerPde = MiAddressToPde(Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if it's not valid
|
// Check if it's not valid
|
||||||
//
|
//
|
||||||
|
@ -154,7 +153,7 @@ MiCheckPdeForPagedPool(IN PVOID Address)
|
||||||
MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)].u.Long);
|
MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)].u.Long);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return status
|
// Return status
|
||||||
//
|
//
|
||||||
|
@ -169,15 +168,15 @@ MiZeroPfn(IN PFN_NUMBER PageFrameNumber)
|
||||||
MMPTE TempPte;
|
MMPTE TempPte;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
PVOID ZeroAddress;
|
PVOID ZeroAddress;
|
||||||
|
|
||||||
/* Get the PFN for this page */
|
/* Get the PFN for this page */
|
||||||
Pfn1 = MiGetPfnEntry(PageFrameNumber);
|
Pfn1 = MiGetPfnEntry(PageFrameNumber);
|
||||||
ASSERT(Pfn1);
|
ASSERT(Pfn1);
|
||||||
|
|
||||||
/* Grab a system PTE we can use to zero the page */
|
/* Grab a system PTE we can use to zero the page */
|
||||||
ZeroPte = MiReserveSystemPtes(1, SystemPteSpace);
|
ZeroPte = MiReserveSystemPtes(1, SystemPteSpace);
|
||||||
ASSERT(ZeroPte);
|
ASSERT(ZeroPte);
|
||||||
|
|
||||||
/* Initialize the PTE for it */
|
/* Initialize the PTE for it */
|
||||||
TempPte = ValidKernelPte;
|
TempPte = ValidKernelPte;
|
||||||
TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
|
TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
|
||||||
|
@ -221,7 +220,7 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n",
|
DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n",
|
||||||
Address,
|
Address,
|
||||||
Process);
|
Process);
|
||||||
|
|
||||||
/* Must currently only be called by paging path */
|
/* Must currently only be called by paging path */
|
||||||
if ((Process) && (OldIrql == MM_NOIRQL))
|
if ((Process) && (OldIrql == MM_NOIRQL))
|
||||||
{
|
{
|
||||||
|
@ -230,11 +229,11 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
|
|
||||||
/* No forking yet */
|
/* No forking yet */
|
||||||
ASSERT(Process->ForkInProgress == NULL);
|
ASSERT(Process->ForkInProgress == NULL);
|
||||||
|
|
||||||
/* Get process color */
|
/* Get process color */
|
||||||
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
|
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
|
||||||
ASSERT(Color != 0xFFFFFFFF);
|
ASSERT(Color != 0xFFFFFFFF);
|
||||||
|
|
||||||
/* We'll need a zero page */
|
/* We'll need a zero page */
|
||||||
NeedZero = TRUE;
|
NeedZero = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -242,7 +241,7 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
{
|
{
|
||||||
/* Check if we need a zero page */
|
/* Check if we need a zero page */
|
||||||
NeedZero = (OldIrql != MM_NOIRQL);
|
NeedZero = (OldIrql != MM_NOIRQL);
|
||||||
|
|
||||||
/* Get the next system page color */
|
/* Get the next system page color */
|
||||||
Color = MI_GET_NEXT_COLOR();
|
Color = MI_GET_NEXT_COLOR();
|
||||||
}
|
}
|
||||||
|
@ -254,10 +253,10 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
HaveLock = TRUE;
|
HaveLock = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We either manually locked the PFN DB, or already came with it locked */
|
/* We either manually locked the PFN DB, or already came with it locked */
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
|
||||||
/* Do we need a zero page? */
|
/* Do we need a zero page? */
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 0);
|
ASSERT(PointerPte->u.Hard.Valid == 0);
|
||||||
#if MI_TRACE_PFNS
|
#if MI_TRACE_PFNS
|
||||||
|
@ -291,21 +290,21 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
/* System wants a zero page, obtain one */
|
/* System wants a zero page, obtain one */
|
||||||
PageFrameNumber = MiRemoveZeroPage(Color);
|
PageFrameNumber = MiRemoveZeroPage(Color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize it */
|
/* Initialize it */
|
||||||
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
|
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
|
||||||
|
|
||||||
/* Release PFN lock if needed */
|
/* Release PFN lock if needed */
|
||||||
if (HaveLock) KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
if (HaveLock) KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Increment demand zero faults
|
// Increment demand zero faults
|
||||||
//
|
//
|
||||||
InterlockedIncrement(&KeGetCurrentPrcb()->MmDemandZeroCount);
|
InterlockedIncrement(&KeGetCurrentPrcb()->MmDemandZeroCount);
|
||||||
|
|
||||||
/* Zero the page if need be */
|
/* Zero the page if need be */
|
||||||
if (NeedZero) MiZeroPfn(PageFrameNumber);
|
if (NeedZero) MiZeroPfn(PageFrameNumber);
|
||||||
|
|
||||||
/* Build the PTE */
|
/* Build the PTE */
|
||||||
if (PointerPte <= MiHighestUserPte)
|
if (PointerPte <= MiHighestUserPte)
|
||||||
{
|
{
|
||||||
|
@ -323,10 +322,10 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
PointerPte->u.Soft.Protection,
|
PointerPte->u.Soft.Protection,
|
||||||
PageFrameNumber);
|
PageFrameNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set it dirty if it's a writable page */
|
/* Set it dirty if it's a writable page */
|
||||||
if (MI_IS_PAGE_WRITEABLE(&TempPte)) MI_MAKE_DIRTY_PAGE(&TempPte);
|
if (MI_IS_PAGE_WRITEABLE(&TempPte)) MI_MAKE_DIRTY_PAGE(&TempPte);
|
||||||
|
|
||||||
/* Write it */
|
/* Write it */
|
||||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
|
||||||
|
@ -350,20 +349,20 @@ MiCompleteProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
PMMPTE OriginalPte;
|
PMMPTE OriginalPte;
|
||||||
ULONG Protection;
|
ULONG Protection;
|
||||||
PFN_NUMBER PageFrameIndex;
|
PFN_NUMBER PageFrameIndex;
|
||||||
|
|
||||||
/* Must be called with an valid prototype PTE, with the PFN lock held */
|
/* Must be called with an valid prototype PTE, with the PFN lock held */
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
ASSERT(PointerProtoPte->u.Hard.Valid == 1);
|
ASSERT(PointerProtoPte->u.Hard.Valid == 1);
|
||||||
|
|
||||||
/* Get the page */
|
/* Get the page */
|
||||||
PageFrameIndex = PFN_FROM_PTE(PointerProtoPte);
|
PageFrameIndex = PFN_FROM_PTE(PointerProtoPte);
|
||||||
|
|
||||||
/* Get the PFN entry and set it as a prototype PTE */
|
/* Get the PFN entry and set it as a prototype PTE */
|
||||||
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
||||||
Pfn1->u3.e1.PrototypePte = 1;
|
Pfn1->u3.e1.PrototypePte = 1;
|
||||||
|
|
||||||
/* FIXME: Increment the share count for the page table */
|
/* FIXME: Increment the share count for the page table */
|
||||||
|
|
||||||
/* Check where we should be getting the protection information from */
|
/* Check where we should be getting the protection information from */
|
||||||
if (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
|
if (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
|
||||||
{
|
{
|
||||||
|
@ -379,10 +378,10 @@ MiCompleteProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
|
|
||||||
/* Release the PFN lock */
|
/* Release the PFN lock */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
/* Remove caching bits */
|
/* Remove caching bits */
|
||||||
Protection &= ~(MM_NOCACHE | MM_NOACCESS);
|
Protection &= ~(MM_NOCACHE | MM_NOACCESS);
|
||||||
|
|
||||||
/* Check if this is a kernel or user address */
|
/* Check if this is a kernel or user address */
|
||||||
if (Address < MmSystemRangeStart)
|
if (Address < MmSystemRangeStart)
|
||||||
{
|
{
|
||||||
|
@ -394,7 +393,7 @@ MiCompleteProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
/* Build the kernel PTE */
|
/* Build the kernel PTE */
|
||||||
MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, PageFrameIndex);
|
MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, PageFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the PTE */
|
/* Write the PTE */
|
||||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
|
||||||
|
@ -419,7 +418,7 @@ MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
PFN_NUMBER PageFrameIndex;
|
PFN_NUMBER PageFrameIndex;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
/* Must be called with an invalid, prototype PTE, with the PFN lock held */
|
/* Must be called with an invalid, prototype PTE, with the PFN lock held */
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 0);
|
ASSERT(PointerPte->u.Hard.Valid == 0);
|
||||||
|
@ -433,10 +432,10 @@ MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
PageFrameIndex = PFN_FROM_PTE(&TempPte);
|
PageFrameIndex = PFN_FROM_PTE(&TempPte);
|
||||||
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
||||||
Pfn1->u2.ShareCount++;
|
Pfn1->u2.ShareCount++;
|
||||||
|
|
||||||
/* Call it a transition */
|
/* Call it a transition */
|
||||||
InterlockedIncrement(&KeGetCurrentPrcb()->MmTransitionCount);
|
InterlockedIncrement(&KeGetCurrentPrcb()->MmTransitionCount);
|
||||||
|
|
||||||
/* Complete the prototype PTE fault -- this will release the PFN lock */
|
/* Complete the prototype PTE fault -- this will release the PFN lock */
|
||||||
return MiCompleteProtoPteFault(StoreInstruction,
|
return MiCompleteProtoPteFault(StoreInstruction,
|
||||||
Address,
|
Address,
|
||||||
|
@ -445,7 +444,7 @@ MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
OldIrql,
|
OldIrql,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure there's some protection mask */
|
/* Make sure there's some protection mask */
|
||||||
if (TempPte.u.Long == 0)
|
if (TempPte.u.Long == 0)
|
||||||
{
|
{
|
||||||
|
@ -454,7 +453,7 @@ MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
return STATUS_ACCESS_VIOLATION;
|
return STATUS_ACCESS_VIOLATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the only thing we support right now */
|
/* This is the only thing we support right now */
|
||||||
ASSERT(TempPte.u.Soft.PageFileHigh == 0);
|
ASSERT(TempPte.u.Soft.PageFileHigh == 0);
|
||||||
ASSERT(TempPte.u.Proto.ReadOnly == 0);
|
ASSERT(TempPte.u.Proto.ReadOnly == 0);
|
||||||
|
@ -465,7 +464,7 @@ MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
/* Resolve the demand zero fault */
|
/* Resolve the demand zero fault */
|
||||||
Status = MiResolveDemandZeroFault(Address, PointerProtoPte, Process, OldIrql);
|
Status = MiResolveDemandZeroFault(Address, PointerProtoPte, Process, OldIrql);
|
||||||
ASSERT(NT_SUCCESS(Status));
|
ASSERT(NT_SUCCESS(Status));
|
||||||
|
|
||||||
/* Complete the prototype PTE fault -- this will release the PFN lock */
|
/* Complete the prototype PTE fault -- this will release the PFN lock */
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 0);
|
ASSERT(PointerPte->u.Hard.Valid == 0);
|
||||||
return MiCompleteProtoPteFault(StoreInstruction,
|
return MiCompleteProtoPteFault(StoreInstruction,
|
||||||
|
@ -494,32 +493,32 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
||||||
DPRINT("ARM3 Page Fault Dispatcher for address: %p in process: %p\n",
|
DPRINT("ARM3 Page Fault Dispatcher for address: %p in process: %p\n",
|
||||||
Address,
|
Address,
|
||||||
Process);
|
Process);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make sure APCs are off and we're not at dispatch
|
// Make sure APCs are off and we're not at dispatch
|
||||||
//
|
//
|
||||||
OldIrql = KeGetCurrentIrql();
|
OldIrql = KeGetCurrentIrql();
|
||||||
ASSERT(OldIrql <= APC_LEVEL);
|
ASSERT(OldIrql <= APC_LEVEL);
|
||||||
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Grab a copy of the PTE
|
// Grab a copy of the PTE
|
||||||
//
|
//
|
||||||
TempPte = *PointerPte;
|
TempPte = *PointerPte;
|
||||||
|
|
||||||
/* Do we have a prototype PTE? */
|
/* Do we have a prototype PTE? */
|
||||||
if (PointerProtoPte)
|
if (PointerProtoPte)
|
||||||
{
|
{
|
||||||
/* This should never happen */
|
/* This should never happen */
|
||||||
ASSERT(!MI_IS_PHYSICAL_ADDRESS(PointerProtoPte));
|
ASSERT(!MI_IS_PHYSICAL_ADDRESS(PointerProtoPte));
|
||||||
|
|
||||||
/* Check if this is a kernel-mode address */
|
/* Check if this is a kernel-mode address */
|
||||||
SuperProtoPte = MiAddressToPte(PointerProtoPte);
|
SuperProtoPte = MiAddressToPte(PointerProtoPte);
|
||||||
if (Address >= MmSystemRangeStart)
|
if (Address >= MmSystemRangeStart)
|
||||||
{
|
{
|
||||||
/* Lock the PFN database */
|
/* Lock the PFN database */
|
||||||
LockIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
LockIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
/* Has the PTE been made valid yet? */
|
/* Has the PTE been made valid yet? */
|
||||||
if (!SuperProtoPte->u.Hard.Valid)
|
if (!SuperProtoPte->u.Hard.Valid)
|
||||||
{
|
{
|
||||||
|
@ -554,10 +553,10 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
||||||
/* We currently only handle very limited paths */
|
/* We currently only handle very limited paths */
|
||||||
ASSERT(PointerPte->u.Soft.Prototype == 1);
|
ASSERT(PointerPte->u.Soft.Prototype == 1);
|
||||||
ASSERT(PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED);
|
ASSERT(PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED);
|
||||||
|
|
||||||
/* Lock the PFN database */
|
/* Lock the PFN database */
|
||||||
LockIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
LockIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
/* For our current usage, this should be true */
|
/* For our current usage, this should be true */
|
||||||
ASSERT(SuperProtoPte->u.Hard.Valid == 1);
|
ASSERT(SuperProtoPte->u.Hard.Valid == 1);
|
||||||
ASSERT(TempPte.u.Hard.Valid == 0);
|
ASSERT(TempPte.u.Hard.Valid == 0);
|
||||||
|
@ -582,20 +581,20 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
||||||
return STATUS_PAGE_FAULT_TRANSITION;
|
return STATUS_PAGE_FAULT_TRANSITION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// The PTE must be invalid, but not totally blank
|
// The PTE must be invalid, but not totally blank
|
||||||
//
|
//
|
||||||
ASSERT(TempPte.u.Hard.Valid == 0);
|
ASSERT(TempPte.u.Hard.Valid == 0);
|
||||||
ASSERT(TempPte.u.Long != 0);
|
ASSERT(TempPte.u.Long != 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// No prototype, transition or page file software PTEs in ARM3 yet
|
// No prototype, transition or page file software PTEs in ARM3 yet
|
||||||
//
|
//
|
||||||
ASSERT(TempPte.u.Soft.Prototype == 0);
|
ASSERT(TempPte.u.Soft.Prototype == 0);
|
||||||
ASSERT(TempPte.u.Soft.Transition == 0);
|
ASSERT(TempPte.u.Soft.Transition == 0);
|
||||||
ASSERT(TempPte.u.Soft.PageFileHigh == 0);
|
ASSERT(TempPte.u.Soft.PageFileHigh == 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// If we got this far, the PTE can only be a demand zero PTE, which is what
|
// If we got this far, the PTE can only be a demand zero PTE, which is what
|
||||||
// we want. Go handle it!
|
// we want. Go handle it!
|
||||||
|
@ -641,7 +640,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
PFN_NUMBER PageFrameIndex;
|
PFN_NUMBER PageFrameIndex;
|
||||||
ULONG Color;
|
ULONG Color;
|
||||||
DPRINT("ARM3 FAULT AT: %p\n", Address);
|
DPRINT("ARM3 FAULT AT: %p\n", Address);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the PTE and PDE
|
// Get the PTE and PDE
|
||||||
//
|
//
|
||||||
|
@ -665,7 +664,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
OldIrql);
|
OldIrql);
|
||||||
ASSERT(OldIrql <= APC_LEVEL);
|
ASSERT(OldIrql <= APC_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check for kernel fault
|
// Check for kernel fault
|
||||||
//
|
//
|
||||||
|
@ -675,7 +674,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
// What are you even DOING here?
|
// What are you even DOING here?
|
||||||
//
|
//
|
||||||
if (Mode == UserMode) return STATUS_ACCESS_VIOLATION;
|
if (Mode == UserMode) return STATUS_ACCESS_VIOLATION;
|
||||||
|
|
||||||
#if (_MI_PAGING_LEVELS >= 3)
|
#if (_MI_PAGING_LEVELS >= 3)
|
||||||
/* Need to check PXE and PDE validity */
|
/* Need to check PXE and PDE validity */
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
|
@ -690,7 +689,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
// Debug spew (eww!)
|
// Debug spew (eww!)
|
||||||
//
|
//
|
||||||
DPRINT("Invalid PDE\n");
|
DPRINT("Invalid PDE\n");
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
#if (_MI_PAGING_LEVELS == 2)
|
||||||
//
|
//
|
||||||
// Handle mapping in "Special" PDE directoreis
|
// Handle mapping in "Special" PDE directoreis
|
||||||
//
|
//
|
||||||
|
@ -704,7 +703,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
//
|
//
|
||||||
// FIXFIX: Do the S-LIST hack
|
// FIXFIX: Do the S-LIST hack
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// Kill the system
|
// Kill the system
|
||||||
//
|
//
|
||||||
|
@ -715,7 +714,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
2);
|
2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// The PDE is valid, so read the PTE
|
// The PDE is valid, so read the PTE
|
||||||
//
|
//
|
||||||
|
@ -733,19 +732,19 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
DPRINT1("Should NEVER happen on ARM3!!!\n");
|
DPRINT1("Should NEVER happen on ARM3!!!\n");
|
||||||
return STATUS_ACCESS_VIOLATION;
|
return STATUS_ACCESS_VIOLATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Otherwise, the PDE was probably invalid, and all is good now
|
// Otherwise, the PDE was probably invalid, and all is good now
|
||||||
//
|
//
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check for a fault on the page table or hyperspace itself
|
// Check for a fault on the page table or hyperspace itself
|
||||||
//
|
//
|
||||||
if (MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address))
|
if (MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address))
|
||||||
{
|
{
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
#if (_MI_PAGING_LEVELS == 2)
|
||||||
/* Could be paged pool access from a new process -- synchronize the page directories */
|
/* Could be paged pool access from a new process -- synchronize the page directories */
|
||||||
if (MiCheckPdeForPagedPool(Address) == STATUS_WAIT_1)
|
if (MiCheckPdeForPagedPool(Address) == STATUS_WAIT_1)
|
||||||
{
|
{
|
||||||
|
@ -756,15 +755,15 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
/* Otherwise this could be a commit of a virtual address */
|
/* Otherwise this could be a commit of a virtual address */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In this path, we are using the system working set */
|
/* In this path, we are using the system working set */
|
||||||
CurrentThread = PsGetCurrentThread();
|
CurrentThread = PsGetCurrentThread();
|
||||||
WorkingSet = &MmSystemCacheWs;
|
WorkingSet = &MmSystemCacheWs;
|
||||||
|
|
||||||
/* Acquire it */
|
/* Acquire it */
|
||||||
KeRaiseIrql(APC_LEVEL, &LockIrql);
|
KeRaiseIrql(APC_LEVEL, &LockIrql);
|
||||||
MiLockWorkingSet(CurrentThread, WorkingSet);
|
MiLockWorkingSet(CurrentThread, WorkingSet);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Re-read PTE now that the IRQL has been raised
|
// Re-read PTE now that the IRQL has been raised
|
||||||
//
|
//
|
||||||
|
@ -782,17 +781,17 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
DPRINT1("Should NEVER happen on ARM3!!!\n");
|
DPRINT1("Should NEVER happen on ARM3!!!\n");
|
||||||
return STATUS_ACCESS_VIOLATION;
|
return STATUS_ACCESS_VIOLATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the working set */
|
/* Release the working set */
|
||||||
MiUnlockWorkingSet(CurrentThread, WorkingSet);
|
MiUnlockWorkingSet(CurrentThread, WorkingSet);
|
||||||
KeLowerIrql(LockIrql);
|
KeLowerIrql(LockIrql);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Otherwise, the PDE was probably invalid, and all is good now
|
// Otherwise, the PDE was probably invalid, and all is good now
|
||||||
//
|
//
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check one kind of prototype PTE */
|
/* Check one kind of prototype PTE */
|
||||||
if (TempPte.u.Soft.Prototype)
|
if (TempPte.u.Soft.Prototype)
|
||||||
{
|
{
|
||||||
|
@ -811,17 +810,17 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
Mode,
|
Mode,
|
||||||
4);
|
4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the prototype PTE! */
|
/* Get the prototype PTE! */
|
||||||
ProtoPte = MiProtoPteToPte(&TempPte);
|
ProtoPte = MiProtoPteToPte(&TempPte);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// We don't implement transition PTEs
|
// We don't implement transition PTEs
|
||||||
//
|
//
|
||||||
ASSERT(TempPte.u.Soft.Transition == 0);
|
ASSERT(TempPte.u.Soft.Transition == 0);
|
||||||
|
|
||||||
/* Check for no-access PTE */
|
/* Check for no-access PTE */
|
||||||
if (TempPte.u.Soft.Protection == MM_NOACCESS)
|
if (TempPte.u.Soft.Protection == MM_NOACCESS)
|
||||||
{
|
{
|
||||||
|
@ -833,7 +832,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for demand page */
|
/* Check for demand page */
|
||||||
if ((StoreInstruction) && !(ProtoPte) && !(TempPte.u.Hard.Valid))
|
if ((StoreInstruction) && !(ProtoPte) && !(TempPte.u.Hard.Valid))
|
||||||
{
|
{
|
||||||
|
@ -848,7 +847,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
14);
|
14);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now do the real fault handling
|
// Now do the real fault handling
|
||||||
//
|
//
|
||||||
|
@ -865,21 +864,21 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
||||||
MiUnlockWorkingSet(CurrentThread, WorkingSet);
|
MiUnlockWorkingSet(CurrentThread, WorkingSet);
|
||||||
KeLowerIrql(LockIrql);
|
KeLowerIrql(LockIrql);
|
||||||
|
|
||||||
//
|
//
|
||||||
// We are done!
|
// We are done!
|
||||||
//
|
//
|
||||||
DPRINT("Fault resolved with status: %lx\n", Status);
|
DPRINT("Fault resolved with status: %lx\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is a user fault */
|
/* This is a user fault */
|
||||||
CurrentThread = PsGetCurrentThread();
|
CurrentThread = PsGetCurrentThread();
|
||||||
CurrentProcess = PsGetCurrentProcess();
|
CurrentProcess = PsGetCurrentProcess();
|
||||||
|
|
||||||
/* Lock the working set */
|
/* Lock the working set */
|
||||||
MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
|
MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
|
||||||
|
|
||||||
#if (_MI_PAGING_LEVELS >= 3)
|
#if (_MI_PAGING_LEVELS >= 3)
|
||||||
/* Need to check/handle PPE and PXE validity too */
|
/* Need to check/handle PPE and PXE validity too */
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
|
@ -894,7 +893,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
|
|
||||||
/* Check if this address range belongs to a valid allocation (VAD) */
|
/* Check if this address range belongs to a valid allocation (VAD) */
|
||||||
MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
|
MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
|
||||||
|
|
||||||
/* Right now, we expect a valid protection mask on the VAD */
|
/* Right now, we expect a valid protection mask on the VAD */
|
||||||
ASSERT(ProtectionCode != MM_NOACCESS);
|
ASSERT(ProtectionCode != MM_NOACCESS);
|
||||||
|
|
||||||
|
@ -928,7 +927,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
/* Now capture the PTE. Ignore virtual faults for now */
|
/* Now capture the PTE. Ignore virtual faults for now */
|
||||||
TempPte = *PointerPte;
|
TempPte = *PointerPte;
|
||||||
ASSERT(TempPte.u.Hard.Valid == 0);
|
ASSERT(TempPte.u.Hard.Valid == 0);
|
||||||
|
|
||||||
/* Quick check for demand-zero */
|
/* Quick check for demand-zero */
|
||||||
if (TempPte.u.Long == (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS))
|
if (TempPte.u.Long == (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS))
|
||||||
{
|
{
|
||||||
|
@ -942,19 +941,19 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
||||||
return STATUS_PAGE_FAULT_DEMAND_ZERO;
|
return STATUS_PAGE_FAULT_DEMAND_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get protection and check if it's a prototype PTE */
|
/* Get protection and check if it's a prototype PTE */
|
||||||
ProtectionCode = TempPte.u.Soft.Protection;
|
ProtectionCode = TempPte.u.Soft.Protection;
|
||||||
ASSERT(TempPte.u.Soft.Prototype == 0);
|
ASSERT(TempPte.u.Soft.Prototype == 0);
|
||||||
|
|
||||||
/* Check for non-demand zero PTE */
|
/* Check for non-demand zero PTE */
|
||||||
if (TempPte.u.Long != 0)
|
if (TempPte.u.Long != 0)
|
||||||
{
|
{
|
||||||
/* This is a page fault, check for valid protection */
|
/* This is a page fault, check for valid protection */
|
||||||
ASSERT(ProtectionCode != 0x100);
|
ASSERT(ProtectionCode != 0x100);
|
||||||
|
|
||||||
/* FIXME: Run MiAccessCheck */
|
/* FIXME: Run MiAccessCheck */
|
||||||
|
|
||||||
/* Dispatch the fault */
|
/* Dispatch the fault */
|
||||||
Status = MiDispatchFault(StoreInstruction,
|
Status = MiDispatchFault(StoreInstruction,
|
||||||
Address,
|
Address,
|
||||||
|
@ -964,7 +963,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
PsGetCurrentProcess(),
|
PsGetCurrentProcess(),
|
||||||
TrapInformation,
|
TrapInformation,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/* Return the status */
|
/* Return the status */
|
||||||
ASSERT(NT_SUCCESS(Status));
|
ASSERT(NT_SUCCESS(Status));
|
||||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||||
|
@ -979,14 +978,14 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
{
|
{
|
||||||
/* This is a bogus VA */
|
/* This is a bogus VA */
|
||||||
Status = STATUS_ACCESS_VIOLATION;
|
Status = STATUS_ACCESS_VIOLATION;
|
||||||
|
|
||||||
/* Could be a not-yet-mapped paged pool page table */
|
/* Could be a not-yet-mapped paged pool page table */
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
#if (_MI_PAGING_LEVELS == 2)
|
||||||
MiCheckPdeForPagedPool(Address);
|
MiCheckPdeForPagedPool(Address);
|
||||||
#endif
|
#endif
|
||||||
/* See if that fixed it */
|
/* See if that fixed it */
|
||||||
if (PointerPte->u.Hard.Valid == 1) Status = STATUS_SUCCESS;
|
if (PointerPte->u.Hard.Valid == 1) Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
/* Return the status */
|
/* Return the status */
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -999,7 +998,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
|
MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
|
||||||
ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT);
|
ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Did we get a prototype PTE back? */
|
/* Did we get a prototype PTE back? */
|
||||||
if (!ProtoPte)
|
if (!ProtoPte)
|
||||||
{
|
{
|
||||||
|
@ -1008,7 +1007,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
|
|
||||||
/* Lock the PFN database since we're going to grab a page */
|
/* Lock the PFN database since we're going to grab a page */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
/* Try to get a zero page */
|
/* Try to get a zero page */
|
||||||
MI_SET_USAGE(MI_USAGE_PEB_TEB);
|
MI_SET_USAGE(MI_USAGE_PEB_TEB);
|
||||||
MI_SET_PROCESS2(CurrentProcess->ImageFileName);
|
MI_SET_PROCESS2(CurrentProcess->ImageFileName);
|
||||||
|
@ -1062,7 +1061,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
|
|
||||||
/* And now write down the PTE, making the address valid */
|
/* And now write down the PTE, making the address valid */
|
||||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
|
||||||
/* Demand zero */
|
/* Demand zero */
|
||||||
Status = STATUS_PAGE_FAULT_DEMAND_ZERO;
|
Status = STATUS_PAGE_FAULT_DEMAND_ZERO;
|
||||||
}
|
}
|
||||||
|
@ -1071,12 +1070,12 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
/* No guard page support yet */
|
/* No guard page support yet */
|
||||||
ASSERT((ProtectionCode & MM_DECOMMIT) == 0);
|
ASSERT((ProtectionCode & MM_DECOMMIT) == 0);
|
||||||
ASSERT(ProtectionCode != 0x100);
|
ASSERT(ProtectionCode != 0x100);
|
||||||
|
|
||||||
/* Write the prototype PTE */
|
/* Write the prototype PTE */
|
||||||
TempPte = PrototypePte;
|
TempPte = PrototypePte;
|
||||||
TempPte.u.Soft.Protection = ProtectionCode;
|
TempPte.u.Soft.Protection = ProtectionCode;
|
||||||
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
||||||
|
|
||||||
/* Handle the fault */
|
/* Handle the fault */
|
||||||
Status = MiDispatchFault(StoreInstruction,
|
Status = MiDispatchFault(StoreInstruction,
|
||||||
Address,
|
Address,
|
||||||
|
@ -1090,7 +1089,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 1);
|
ASSERT(PointerPte->u.Hard.Valid == 1);
|
||||||
ASSERT(PointerPte->u.Hard.PageFrameNumber != 0);
|
ASSERT(PointerPte->u.Hard.PageFrameNumber != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the working set */
|
/* Release the working set */
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
||||||
return Status;
|
return Status;
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::PFNLIST"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -86,14 +85,14 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
|
||||||
ULONG Color;
|
ULONG Color;
|
||||||
PMMCOLOR_TABLES ColorTable;
|
PMMCOLOR_TABLES ColorTable;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
|
|
||||||
/* Make sure the PFN lock is held */
|
/* Make sure the PFN lock is held */
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
|
||||||
/* Make sure the PFN entry isn't in-use */
|
/* Make sure the PFN entry isn't in-use */
|
||||||
ASSERT(Entry->u3.e1.WriteInProgress == 0);
|
ASSERT(Entry->u3.e1.WriteInProgress == 0);
|
||||||
ASSERT(Entry->u3.e1.ReadInProgress == 0);
|
ASSERT(Entry->u3.e1.ReadInProgress == 0);
|
||||||
|
|
||||||
/* Find the list for this entry, make sure it's the free or zero list */
|
/* Find the list for this entry, make sure it's the free or zero list */
|
||||||
ListHead = MmPageLocationList[Entry->u3.e1.PageLocation];
|
ListHead = MmPageLocationList[Entry->u3.e1.PageLocation];
|
||||||
ListName = ListHead->ListName;
|
ListName = ListHead->ListName;
|
||||||
|
@ -104,11 +103,11 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
|
||||||
/* Remove one count */
|
/* Remove one count */
|
||||||
ASSERT(ListHead->Total != 0);
|
ASSERT(ListHead->Total != 0);
|
||||||
ListHead->Total--;
|
ListHead->Total--;
|
||||||
|
|
||||||
/* Get the forward and back pointers */
|
/* Get the forward and back pointers */
|
||||||
OldFlink = Entry->u1.Flink;
|
OldFlink = Entry->u1.Flink;
|
||||||
OldBlink = Entry->u2.Blink;
|
OldBlink = Entry->u2.Blink;
|
||||||
|
|
||||||
/* Check if the next entry is the list head */
|
/* Check if the next entry is the list head */
|
||||||
if (OldFlink != LIST_HEAD)
|
if (OldFlink != LIST_HEAD)
|
||||||
{
|
{
|
||||||
|
@ -120,7 +119,7 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
|
||||||
/* Set the list head's backlink instead */
|
/* Set the list head's backlink instead */
|
||||||
ListHead->Blink = OldBlink;
|
ListHead->Blink = OldBlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the back entry is the list head */
|
/* Check if the back entry is the list head */
|
||||||
if (OldBlink != LIST_HEAD)
|
if (OldBlink != LIST_HEAD)
|
||||||
{
|
{
|
||||||
|
@ -183,7 +182,7 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
|
||||||
/* One less colored page */
|
/* One less colored page */
|
||||||
ASSERT(ColorTable->Count >= 1);
|
ASSERT(ColorTable->Count >= 1);
|
||||||
ColorTable->Count--;
|
ColorTable->Count--;
|
||||||
|
|
||||||
/* ReactOS Hack */
|
/* ReactOS Hack */
|
||||||
Entry->OriginalPte.u.Long = 0;
|
Entry->OriginalPte.u.Long = 0;
|
||||||
|
|
||||||
|
@ -202,13 +201,13 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
|
||||||
/* Signal the low memory event */
|
/* Signal the low memory event */
|
||||||
KeSetEvent(MiLowMemoryEvent, 0, FALSE);
|
KeSetEvent(MiLowMemoryEvent, 0, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* One less page */
|
/* One less page */
|
||||||
if (--MmAvailablePages < MmMinimumFreePages)
|
if (--MmAvailablePages < MmMinimumFreePages)
|
||||||
{
|
{
|
||||||
/* FIXME: Should wake up the MPW and working set manager, if we had one */
|
/* FIXME: Should wake up the MPW and working set manager, if we had one */
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MI_TRACE_PFNS
|
#if MI_TRACE_PFNS
|
||||||
ASSERT(MI_PFN_CURRENT_USAGE != MI_USAGE_NOT_SET);
|
ASSERT(MI_PFN_CURRENT_USAGE != MI_USAGE_NOT_SET);
|
||||||
Entry->PfnUsage = MI_PFN_CURRENT_USAGE;
|
Entry->PfnUsage = MI_PFN_CURRENT_USAGE;
|
||||||
|
@ -238,7 +237,7 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex,
|
||||||
Pfn1 = MI_PFN_ELEMENT(PageIndex);
|
Pfn1 = MI_PFN_ELEMENT(PageIndex);
|
||||||
ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
|
ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
|
||||||
ASSERT(Pfn1->u3.e1.Rom == 0);
|
ASSERT(Pfn1->u3.e1.Rom == 0);
|
||||||
|
|
||||||
/* Capture data for later */
|
/* Capture data for later */
|
||||||
OldColor = Pfn1->u3.e1.PageColor;
|
OldColor = Pfn1->u3.e1.PageColor;
|
||||||
OldCache = Pfn1->u3.e1.CacheAttribute;
|
OldCache = Pfn1->u3.e1.CacheAttribute;
|
||||||
|
@ -248,14 +247,14 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex,
|
||||||
ASSERT_LIST_INVARIANT(ListHead);
|
ASSERT_LIST_INVARIANT(ListHead);
|
||||||
ListName = ListHead->ListName;
|
ListName = ListHead->ListName;
|
||||||
ASSERT(ListName <= FreePageList);
|
ASSERT(ListName <= FreePageList);
|
||||||
|
|
||||||
/* Remove a page */
|
/* Remove a page */
|
||||||
ListHead->Total--;
|
ListHead->Total--;
|
||||||
|
|
||||||
/* Get the forward and back pointers */
|
/* Get the forward and back pointers */
|
||||||
OldFlink = Pfn1->u1.Flink;
|
OldFlink = Pfn1->u1.Flink;
|
||||||
OldBlink = Pfn1->u2.Blink;
|
OldBlink = Pfn1->u2.Blink;
|
||||||
|
|
||||||
/* Check if the next entry is the list head */
|
/* Check if the next entry is the list head */
|
||||||
if (OldFlink != LIST_HEAD)
|
if (OldFlink != LIST_HEAD)
|
||||||
{
|
{
|
||||||
|
@ -267,7 +266,7 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex,
|
||||||
/* Set the list head's backlink instead */
|
/* Set the list head's backlink instead */
|
||||||
ListHead->Blink = OldBlink;
|
ListHead->Blink = OldBlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the back entry is the list head */
|
/* Check if the back entry is the list head */
|
||||||
if (OldBlink != LIST_HEAD)
|
if (OldBlink != LIST_HEAD)
|
||||||
{
|
{
|
||||||
|
@ -279,11 +278,11 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex,
|
||||||
/* Set the list head's backlink instead */
|
/* Set the list head's backlink instead */
|
||||||
ListHead->Flink = OldFlink;
|
ListHead->Flink = OldFlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We are not on a list anymore */
|
/* We are not on a list anymore */
|
||||||
ASSERT_LIST_INVARIANT(ListHead);
|
ASSERT_LIST_INVARIANT(ListHead);
|
||||||
Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
|
Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
|
||||||
|
|
||||||
/* Zero flags but restore color and cache */
|
/* Zero flags but restore color and cache */
|
||||||
Pfn1->u3.e2.ShortFlags = 0;
|
Pfn1->u3.e2.ShortFlags = 0;
|
||||||
Pfn1->u3.e1.PageColor = OldColor;
|
Pfn1->u3.e1.PageColor = OldColor;
|
||||||
|
@ -293,25 +292,25 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex,
|
||||||
ASSERT(Color < MmSecondaryColors);
|
ASSERT(Color < MmSecondaryColors);
|
||||||
ColorTable = &MmFreePagesByColor[ListName][Color];
|
ColorTable = &MmFreePagesByColor[ListName][Color];
|
||||||
ASSERT(ColorTable->Count >= 1);
|
ASSERT(ColorTable->Count >= 1);
|
||||||
|
|
||||||
/* Set the forward link to whoever we were pointing to */
|
/* Set the forward link to whoever we were pointing to */
|
||||||
ColorTable->Flink = Pfn1->OriginalPte.u.Long;
|
ColorTable->Flink = Pfn1->OriginalPte.u.Long;
|
||||||
|
|
||||||
/* Get the first page on the color list */
|
/* Get the first page on the color list */
|
||||||
if (ColorTable->Flink == LIST_HEAD)
|
if (ColorTable->Flink == LIST_HEAD)
|
||||||
{
|
{
|
||||||
/* This is the beginning of the list, so set the sentinel value */
|
/* This is the beginning of the list, so set the sentinel value */
|
||||||
ColorTable->Blink = (PVOID)LIST_HEAD;
|
ColorTable->Blink = (PVOID)LIST_HEAD;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The list is empty, so we are the first page */
|
/* The list is empty, so we are the first page */
|
||||||
MI_PFN_ELEMENT(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD;
|
MI_PFN_ELEMENT(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* One less page */
|
/* One less page */
|
||||||
ColorTable->Count--;
|
ColorTable->Count--;
|
||||||
|
|
||||||
/* ReactOS Hack */
|
/* ReactOS Hack */
|
||||||
Pfn1->OriginalPte.u.Long = 0;
|
Pfn1->OriginalPte.u.Long = 0;
|
||||||
|
|
||||||
|
@ -326,7 +325,7 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex,
|
||||||
/* Signal the low memory event */
|
/* Signal the low memory event */
|
||||||
KeSetEvent(MiLowMemoryEvent, 0, FALSE);
|
KeSetEvent(MiLowMemoryEvent, 0, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* One less page */
|
/* One less page */
|
||||||
if (--MmAvailablePages < MmMinimumFreePages)
|
if (--MmAvailablePages < MmMinimumFreePages)
|
||||||
{
|
{
|
||||||
|
@ -396,7 +395,7 @@ MiRemoveAnyPage(IN ULONG Color)
|
||||||
ASSERT(Pfn1->u2.ShareCount == 0);
|
ASSERT(Pfn1->u2.ShareCount == 0);
|
||||||
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
|
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
|
||||||
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
||||||
|
|
||||||
/* Return the page */
|
/* Return the page */
|
||||||
return PageIndex;
|
return PageIndex;
|
||||||
}
|
}
|
||||||
|
@ -457,10 +456,10 @@ MiRemoveZeroPage(IN ULONG Color)
|
||||||
/* Remove the page from its list */
|
/* Remove the page from its list */
|
||||||
PageIndex = MiRemovePageByColor(PageIndex, Color);
|
PageIndex = MiRemovePageByColor(PageIndex, Color);
|
||||||
ASSERT(Pfn1 == MI_PFN_ELEMENT(PageIndex));
|
ASSERT(Pfn1 == MI_PFN_ELEMENT(PageIndex));
|
||||||
|
|
||||||
/* Zero it, if needed */
|
/* Zero it, if needed */
|
||||||
if (Zero) MiZeroPhysicalPage(PageIndex);
|
if (Zero) MiZeroPhysicalPage(PageIndex);
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
||||||
ASSERT(Pfn1->u2.ShareCount == 0);
|
ASSERT(Pfn1->u2.ShareCount == 0);
|
||||||
|
@ -562,18 +561,18 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
|
||||||
{
|
{
|
||||||
/* Get the previous page */
|
/* Get the previous page */
|
||||||
Blink = (PMMPFN)ColorTable->Blink;
|
Blink = (PMMPFN)ColorTable->Blink;
|
||||||
|
|
||||||
/* Make it link to us, and link back to it */
|
/* Make it link to us, and link back to it */
|
||||||
Blink->OriginalPte.u.Long = PageFrameIndex;
|
Blink->OriginalPte.u.Long = PageFrameIndex;
|
||||||
Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink);
|
Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now initialize our own list pointers */
|
/* Now initialize our own list pointers */
|
||||||
ColorTable->Blink = Pfn1;
|
ColorTable->Blink = Pfn1;
|
||||||
|
|
||||||
/* This page is now the last */
|
/* This page is now the last */
|
||||||
Pfn1->OriginalPte.u.Long = LIST_HEAD;
|
Pfn1->OriginalPte.u.Long = LIST_HEAD;
|
||||||
|
|
||||||
/* And increase the count in the colored list */
|
/* And increase the count in the colored list */
|
||||||
ColorTable->Count++;
|
ColorTable->Count++;
|
||||||
|
|
||||||
|
@ -584,7 +583,7 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
|
||||||
MmZeroingPageThreadActive = TRUE;
|
MmZeroingPageThreadActive = TRUE;
|
||||||
KeSetEvent(&MmZeroingPageEvent, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(&MmZeroingPageEvent, IO_NO_INCREMENT, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MI_TRACE_PFNS
|
#if MI_TRACE_PFNS
|
||||||
Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
|
Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
|
||||||
RtlZeroMemory(Pfn1->ProcessName, 16);
|
RtlZeroMemory(Pfn1->ProcessName, 16);
|
||||||
|
@ -608,12 +607,12 @@ MiInsertPageInList(IN PMMPFNLIST ListHead,
|
||||||
|
|
||||||
/* Make sure the lock is held */
|
/* Make sure the lock is held */
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
|
||||||
/* Make sure the PFN is valid */
|
/* Make sure the PFN is valid */
|
||||||
ASSERT((PageFrameIndex) &&
|
ASSERT((PageFrameIndex) &&
|
||||||
(PageFrameIndex <= MmHighestPhysicalPage) &&
|
(PageFrameIndex <= MmHighestPhysicalPage) &&
|
||||||
(PageFrameIndex >= MmLowestPhysicalPage));
|
(PageFrameIndex >= MmLowestPhysicalPage));
|
||||||
|
|
||||||
/* Page should be unused */
|
/* Page should be unused */
|
||||||
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
||||||
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
||||||
|
@ -653,7 +652,7 @@ MiInsertPageInList(IN PMMPFNLIST ListHead,
|
||||||
|
|
||||||
/* One more page on the system */
|
/* One more page on the system */
|
||||||
MmAvailablePages++;
|
MmAvailablePages++;
|
||||||
|
|
||||||
/* Check if we've reached the configured low memory threshold */
|
/* Check if we've reached the configured low memory threshold */
|
||||||
if (MmAvailablePages == MmLowMemoryThreshold)
|
if (MmAvailablePages == MmLowMemoryThreshold)
|
||||||
{
|
{
|
||||||
|
@ -701,7 +700,7 @@ MiInsertPageInList(IN PMMPFNLIST ListHead,
|
||||||
|
|
||||||
/* One more paged on the colored list */
|
/* One more paged on the colored list */
|
||||||
ColorHead->Count++;
|
ColorHead->Count++;
|
||||||
|
|
||||||
#if MI_TRACE_PFNS
|
#if MI_TRACE_PFNS
|
||||||
//ASSERT(MI_PFN_CURRENT_USAGE == MI_USAGE_NOT_SET);
|
//ASSERT(MI_PFN_CURRENT_USAGE == MI_USAGE_NOT_SET);
|
||||||
Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
|
Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
|
||||||
|
@ -730,7 +729,7 @@ MiInitializePfn(IN PFN_NUMBER PageFrameIndex,
|
||||||
{
|
{
|
||||||
/* Only valid from MmCreateProcessAddressSpace path */
|
/* Only valid from MmCreateProcessAddressSpace path */
|
||||||
ASSERT(PsGetCurrentProcess()->Vm.WorkingSetSize == 0);
|
ASSERT(PsGetCurrentProcess()->Vm.WorkingSetSize == 0);
|
||||||
|
|
||||||
/* Make this a demand zero PTE */
|
/* Make this a demand zero PTE */
|
||||||
MI_MAKE_SOFTWARE_PTE(&Pfn1->OriginalPte, MM_READWRITE);
|
MI_MAKE_SOFTWARE_PTE(&Pfn1->OriginalPte, MM_READWRITE);
|
||||||
}
|
}
|
||||||
|
@ -788,20 +787,20 @@ MiAllocatePfn(IN PMMPTE PointerPte,
|
||||||
|
|
||||||
/* Sanity check that we aren't passed a valid PTE */
|
/* Sanity check that we aren't passed a valid PTE */
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 0);
|
ASSERT(PointerPte->u.Hard.Valid == 0);
|
||||||
|
|
||||||
/* Make an empty software PTE */
|
/* Make an empty software PTE */
|
||||||
MI_MAKE_SOFTWARE_PTE(&TempPte, MM_READWRITE);
|
MI_MAKE_SOFTWARE_PTE(&TempPte, MM_READWRITE);
|
||||||
|
|
||||||
/* Lock the PFN database */
|
/* Lock the PFN database */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
/* Check if we're running low on pages */
|
/* Check if we're running low on pages */
|
||||||
if (MmAvailablePages < 128)
|
if (MmAvailablePages < 128)
|
||||||
{
|
{
|
||||||
DPRINT1("Warning, running low on memory: %d pages left\n", MmAvailablePages);
|
DPRINT1("Warning, running low on memory: %d pages left\n", MmAvailablePages);
|
||||||
//MiEnsureAvailablePageOrWait(NULL, OldIrql);
|
//MiEnsureAvailablePageOrWait(NULL, OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Grab a page */
|
/* Grab a page */
|
||||||
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
|
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
|
||||||
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
||||||
|
@ -810,10 +809,10 @@ MiAllocatePfn(IN PMMPTE PointerPte,
|
||||||
/* Write the software PTE */
|
/* Write the software PTE */
|
||||||
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
||||||
PointerPte->u.Soft.Protection |= Protection;
|
PointerPte->u.Soft.Protection |= Protection;
|
||||||
|
|
||||||
/* Initialize its PFN entry */
|
/* Initialize its PFN entry */
|
||||||
MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
|
MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
|
||||||
|
|
||||||
/* Release the PFN lock and return the page */
|
/* Release the PFN lock and return the page */
|
||||||
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
|
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
|
||||||
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
||||||
|
@ -852,10 +851,10 @@ MiDecrementShareCount(IN PMMPFN Pfn1,
|
||||||
|
|
||||||
/* Put the page in transition */
|
/* Put the page in transition */
|
||||||
Pfn1->u3.e1.PageLocation = TransitionPage;
|
Pfn1->u3.e1.PageLocation = TransitionPage;
|
||||||
|
|
||||||
/* PFN lock must be held */
|
/* PFN lock must be held */
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
|
||||||
/* Page should at least have one reference */
|
/* Page should at least have one reference */
|
||||||
ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
|
ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
|
||||||
if (Pfn1->u3.e2.ReferenceCount == 1)
|
if (Pfn1->u3.e2.ReferenceCount == 1)
|
||||||
|
@ -931,14 +930,14 @@ MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex,
|
||||||
IN PFN_NUMBER PteFrame)
|
IN PFN_NUMBER PteFrame)
|
||||||
{
|
{
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
|
|
||||||
/* Setup the PTE */
|
/* Setup the PTE */
|
||||||
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
||||||
Pfn1->PteAddress = PointerPte;
|
Pfn1->PteAddress = PointerPte;
|
||||||
|
|
||||||
/* Make this a software PTE */
|
/* Make this a software PTE */
|
||||||
MI_MAKE_SOFTWARE_PTE(&Pfn1->OriginalPte, MM_READWRITE);
|
MI_MAKE_SOFTWARE_PTE(&Pfn1->OriginalPte, MM_READWRITE);
|
||||||
|
|
||||||
/* Setup the page */
|
/* Setup the page */
|
||||||
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
||||||
Pfn1->u3.e2.ReferenceCount = 1;
|
Pfn1->u3.e2.ReferenceCount = 1;
|
||||||
|
@ -946,14 +945,14 @@ MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex,
|
||||||
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
||||||
Pfn1->u3.e1.Modified = TRUE;
|
Pfn1->u3.e1.Modified = TRUE;
|
||||||
Pfn1->u4.InPageError = FALSE;
|
Pfn1->u4.InPageError = FALSE;
|
||||||
|
|
||||||
/* Did we get a PFN for the page table */
|
/* Did we get a PFN for the page table */
|
||||||
if (PteFrame)
|
if (PteFrame)
|
||||||
{
|
{
|
||||||
/* Store it */
|
/* Store it */
|
||||||
Pfn1->u4.PteFrame = PteFrame;
|
Pfn1->u4.PteFrame = PteFrame;
|
||||||
|
|
||||||
/* Increase its share count so we don't get rid of it */
|
/* Increase its share count so we don't get rid of it */
|
||||||
Pfn1 = MI_PFN_ELEMENT(PteFrame);
|
Pfn1 = MI_PFN_ELEMENT(PteFrame);
|
||||||
Pfn1->u2.ShareCount++;
|
Pfn1->u2.ShareCount++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::POOL"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -55,7 +54,7 @@ MiProtectFreeNonPagedPool(IN PVOID VirtualAddress,
|
||||||
TempPte.u.Soft.Prototype = 1;
|
TempPte.u.Soft.Prototype = 1;
|
||||||
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
||||||
} while (++PointerPte < LastPte);
|
} while (++PointerPte < LastPte);
|
||||||
|
|
||||||
/* Flush the TLB */
|
/* Flush the TLB */
|
||||||
KeFlushEntireTb(TRUE, TRUE);
|
KeFlushEntireTb(TRUE, TRUE);
|
||||||
}
|
}
|
||||||
|
@ -71,11 +70,11 @@ MiUnProtectFreeNonPagedPool(IN PVOID VirtualAddress,
|
||||||
|
|
||||||
/* If pool is physical, can't protect PTEs */
|
/* If pool is physical, can't protect PTEs */
|
||||||
if (MI_IS_PHYSICAL_ADDRESS(VirtualAddress)) return FALSE;
|
if (MI_IS_PHYSICAL_ADDRESS(VirtualAddress)) return FALSE;
|
||||||
|
|
||||||
/* Get, and capture the PTE */
|
/* Get, and capture the PTE */
|
||||||
PointerPte = MiAddressToPte(VirtualAddress);
|
PointerPte = MiAddressToPte(VirtualAddress);
|
||||||
TempPte = *PointerPte;
|
TempPte = *PointerPte;
|
||||||
|
|
||||||
/* Loop protected PTEs */
|
/* Loop protected PTEs */
|
||||||
while ((TempPte.u.Hard.Valid == 0) && (TempPte.u.Soft.Prototype == 1))
|
while ((TempPte.u.Hard.Valid == 0) && (TempPte.u.Soft.Prototype == 1))
|
||||||
{
|
{
|
||||||
|
@ -83,14 +82,14 @@ MiUnProtectFreeNonPagedPool(IN PVOID VirtualAddress,
|
||||||
TempPte.u.Hard.Valid = 1;
|
TempPte.u.Hard.Valid = 1;
|
||||||
TempPte.u.Soft.Prototype = 0;
|
TempPte.u.Soft.Prototype = 0;
|
||||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
|
||||||
/* One more page */
|
/* One more page */
|
||||||
if (++UnprotectedPages == PageCount) break;
|
if (++UnprotectedPages == PageCount) break;
|
||||||
|
|
||||||
/* Capture next PTE */
|
/* Capture next PTE */
|
||||||
TempPte = *(++PointerPte);
|
TempPte = *(++PointerPte);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return if any pages were unprotected */
|
/* Return if any pages were unprotected */
|
||||||
return UnprotectedPages ? TRUE : FALSE;
|
return UnprotectedPages ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
@ -103,27 +102,27 @@ MiProtectedPoolUnProtectLinks(IN PLIST_ENTRY Links,
|
||||||
{
|
{
|
||||||
BOOLEAN Safe;
|
BOOLEAN Safe;
|
||||||
PVOID PoolVa;
|
PVOID PoolVa;
|
||||||
|
|
||||||
/* Initialize variables */
|
/* Initialize variables */
|
||||||
*PoolFlink = *PoolBlink = NULL;
|
*PoolFlink = *PoolBlink = NULL;
|
||||||
|
|
||||||
/* Check if the list has entries */
|
/* Check if the list has entries */
|
||||||
if (IsListEmpty(Links) == FALSE)
|
if (IsListEmpty(Links) == FALSE)
|
||||||
{
|
{
|
||||||
/* We are going to need to forward link to do an insert */
|
/* We are going to need to forward link to do an insert */
|
||||||
PoolVa = Links->Flink;
|
PoolVa = Links->Flink;
|
||||||
|
|
||||||
/* So make it safe to access */
|
/* So make it safe to access */
|
||||||
Safe = MiUnProtectFreeNonPagedPool(PoolVa, 1);
|
Safe = MiUnProtectFreeNonPagedPool(PoolVa, 1);
|
||||||
if (Safe) PoolFlink = PoolVa;
|
if (Safe) PoolFlink = PoolVa;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Are we going to need a backward link too? */
|
/* Are we going to need a backward link too? */
|
||||||
if (Links != Links->Blink)
|
if (Links != Links->Blink)
|
||||||
{
|
{
|
||||||
/* Get the head's backward link for the insert */
|
/* Get the head's backward link for the insert */
|
||||||
PoolVa = Links->Blink;
|
PoolVa = Links->Blink;
|
||||||
|
|
||||||
/* Make it safe to access */
|
/* Make it safe to access */
|
||||||
Safe = MiUnProtectFreeNonPagedPool(PoolVa, 1);
|
Safe = MiUnProtectFreeNonPagedPool(PoolVa, 1);
|
||||||
if (Safe) PoolBlink = PoolVa;
|
if (Safe) PoolBlink = PoolVa;
|
||||||
|
@ -147,13 +146,13 @@ MiProtectedPoolInsertList(IN PLIST_ENTRY ListHead,
|
||||||
IN BOOLEAN Critical)
|
IN BOOLEAN Critical)
|
||||||
{
|
{
|
||||||
PVOID PoolFlink, PoolBlink;
|
PVOID PoolFlink, PoolBlink;
|
||||||
|
|
||||||
/* Make the list accessible */
|
/* Make the list accessible */
|
||||||
MiProtectedPoolUnProtectLinks(ListHead, &PoolFlink, &PoolBlink);
|
MiProtectedPoolUnProtectLinks(ListHead, &PoolFlink, &PoolBlink);
|
||||||
|
|
||||||
/* Now insert in the right position */
|
/* Now insert in the right position */
|
||||||
Critical ? InsertHeadList(ListHead, Entry) : InsertTailList(ListHead, Entry);
|
Critical ? InsertHeadList(ListHead, Entry) : InsertTailList(ListHead, Entry);
|
||||||
|
|
||||||
/* And reprotect the pages containing the free links */
|
/* And reprotect the pages containing the free links */
|
||||||
MiProtectedPoolProtectLinks(PoolFlink, PoolBlink);
|
MiProtectedPoolProtectLinks(PoolFlink, PoolBlink);
|
||||||
}
|
}
|
||||||
|
@ -163,13 +162,13 @@ NTAPI
|
||||||
MiProtectedPoolRemoveEntryList(IN PLIST_ENTRY Entry)
|
MiProtectedPoolRemoveEntryList(IN PLIST_ENTRY Entry)
|
||||||
{
|
{
|
||||||
PVOID PoolFlink, PoolBlink;
|
PVOID PoolFlink, PoolBlink;
|
||||||
|
|
||||||
/* Make the list accessible */
|
/* Make the list accessible */
|
||||||
MiProtectedPoolUnProtectLinks(Entry, &PoolFlink, &PoolBlink);
|
MiProtectedPoolUnProtectLinks(Entry, &PoolFlink, &PoolBlink);
|
||||||
|
|
||||||
/* Now remove */
|
/* Now remove */
|
||||||
RemoveEntryList(Entry);
|
RemoveEntryList(Entry);
|
||||||
|
|
||||||
/* And reprotect the pages containing the free links */
|
/* And reprotect the pages containing the free links */
|
||||||
if (PoolFlink) MiProtectFreeNonPagedPool(PoolFlink, 1);
|
if (PoolFlink) MiProtectFreeNonPagedPool(PoolFlink, 1);
|
||||||
if (PoolBlink) MiProtectFreeNonPagedPool(PoolBlink, 1);
|
if (PoolBlink) MiProtectFreeNonPagedPool(PoolBlink, 1);
|
||||||
|
@ -294,7 +293,7 @@ MiInitializeNonPagedPool(VOID)
|
||||||
//
|
//
|
||||||
PoolPages = BYTES_TO_PAGES(MmSizeOfNonPagedPoolInBytes);
|
PoolPages = BYTES_TO_PAGES(MmSizeOfNonPagedPoolInBytes);
|
||||||
MmNumberOfFreeNonPagedPool = PoolPages;
|
MmNumberOfFreeNonPagedPool = PoolPages;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize the first free entry
|
// Initialize the first free entry
|
||||||
//
|
//
|
||||||
|
@ -309,7 +308,7 @@ MiInitializeNonPagedPool(VOID)
|
||||||
//
|
//
|
||||||
InsertHeadList(&MmNonPagedPoolFreeListHead[MI_MAX_FREE_PAGE_LISTS - 1],
|
InsertHeadList(&MmNonPagedPoolFreeListHead[MI_MAX_FREE_PAGE_LISTS - 1],
|
||||||
&FreeEntry->List);
|
&FreeEntry->List);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now create free entries for every single other page
|
// Now create free entries for every single other page
|
||||||
//
|
//
|
||||||
|
@ -329,37 +328,37 @@ MiInitializeNonPagedPool(VOID)
|
||||||
PointerPte = MiAddressToPte(MmNonPagedPoolStart);
|
PointerPte = MiAddressToPte(MmNonPagedPoolStart);
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 1);
|
ASSERT(PointerPte->u.Hard.Valid == 1);
|
||||||
MiStartOfInitialPoolFrame = PFN_FROM_PTE(PointerPte);
|
MiStartOfInitialPoolFrame = PFN_FROM_PTE(PointerPte);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Keep track of where initial nonpaged pool ends
|
// Keep track of where initial nonpaged pool ends
|
||||||
//
|
//
|
||||||
MmNonPagedPoolEnd0 = (PVOID)((ULONG_PTR)MmNonPagedPoolStart +
|
MmNonPagedPoolEnd0 = (PVOID)((ULONG_PTR)MmNonPagedPoolStart +
|
||||||
MmSizeOfNonPagedPoolInBytes);
|
MmSizeOfNonPagedPoolInBytes);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Validate and remember last allocated pool page
|
// Validate and remember last allocated pool page
|
||||||
//
|
//
|
||||||
PointerPte = MiAddressToPte((PVOID)((ULONG_PTR)MmNonPagedPoolEnd0 - 1));
|
PointerPte = MiAddressToPte((PVOID)((ULONG_PTR)MmNonPagedPoolEnd0 - 1));
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 1);
|
ASSERT(PointerPte->u.Hard.Valid == 1);
|
||||||
MiEndOfInitialPoolFrame = PFN_FROM_PTE(PointerPte);
|
MiEndOfInitialPoolFrame = PFN_FROM_PTE(PointerPte);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Validate the first nonpaged pool expansion page (which is a guard page)
|
// Validate the first nonpaged pool expansion page (which is a guard page)
|
||||||
//
|
//
|
||||||
PointerPte = MiAddressToPte(MmNonPagedPoolExpansionStart);
|
PointerPte = MiAddressToPte(MmNonPagedPoolExpansionStart);
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 0);
|
ASSERT(PointerPte->u.Hard.Valid == 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Calculate the size of the expansion region alone
|
// Calculate the size of the expansion region alone
|
||||||
//
|
//
|
||||||
MiExpansionPoolPagesInitialCharge =
|
MiExpansionPoolPagesInitialCharge =
|
||||||
BYTES_TO_PAGES(MmMaximumNonPagedPoolInBytes - MmSizeOfNonPagedPoolInBytes);
|
BYTES_TO_PAGES(MmMaximumNonPagedPoolInBytes - MmSizeOfNonPagedPoolInBytes);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Remove 2 pages, since there's a guard page on top and on the bottom
|
// Remove 2 pages, since there's a guard page on top and on the bottom
|
||||||
//
|
//
|
||||||
MiExpansionPoolPagesInitialCharge -= 2;
|
MiExpansionPoolPagesInitialCharge -= 2;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now initialize the nonpaged pool expansion PTE space. Remember there's a
|
// Now initialize the nonpaged pool expansion PTE space. Remember there's a
|
||||||
// guard page on top so make sure to skip it. The bottom guard page will be
|
// guard page on top so make sure to skip it. The bottom guard page will be
|
||||||
|
@ -388,12 +387,12 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
PVOID BaseVa, BaseVaStart;
|
PVOID BaseVa, BaseVaStart;
|
||||||
PMMFREE_POOL_ENTRY FreeEntry;
|
PMMFREE_POOL_ENTRY FreeEntry;
|
||||||
PKSPIN_LOCK_QUEUE LockQueue;
|
PKSPIN_LOCK_QUEUE LockQueue;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Figure out how big the allocation is in pages
|
// Figure out how big the allocation is in pages
|
||||||
//
|
//
|
||||||
SizeInPages = BYTES_TO_PAGES(SizeInBytes);
|
SizeInPages = BYTES_TO_PAGES(SizeInBytes);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle paged pool
|
// Handle paged pool
|
||||||
//
|
//
|
||||||
|
@ -403,7 +402,7 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
// Lock the paged pool mutex
|
// Lock the paged pool mutex
|
||||||
//
|
//
|
||||||
KeAcquireGuardedMutex(&MmPagedPoolMutex);
|
KeAcquireGuardedMutex(&MmPagedPoolMutex);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Find some empty allocation space
|
// Find some empty allocation space
|
||||||
//
|
//
|
||||||
|
@ -417,7 +416,7 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
//
|
//
|
||||||
i = ((SizeInPages - 1) / PTE_COUNT) + 1;
|
i = ((SizeInPages - 1) / PTE_COUNT) + 1;
|
||||||
DPRINT1("Paged pool expansion: %d %x\n", i, SizeInPages);
|
DPRINT1("Paged pool expansion: %d %x\n", i, SizeInPages);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if there is enougn paged pool expansion space left
|
// Check if there is enougn paged pool expansion space left
|
||||||
//
|
//
|
||||||
|
@ -431,17 +430,17 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
KeReleaseGuardedMutex(&MmPagedPoolMutex);
|
KeReleaseGuardedMutex(&MmPagedPoolMutex);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we'll have to expand past the last PTE we have available
|
// Check if we'll have to expand past the last PTE we have available
|
||||||
//
|
//
|
||||||
if (((i - 1) + MmPagedPoolInfo.NextPdeForPagedPoolExpansion) >
|
if (((i - 1) + MmPagedPoolInfo.NextPdeForPagedPoolExpansion) >
|
||||||
(PMMPDE)MiAddressToPte(MmPagedPoolInfo.LastPteForPagedPool))
|
(PMMPDE)MiAddressToPte(MmPagedPoolInfo.LastPteForPagedPool))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// We can only support this much then
|
// We can only support this much then
|
||||||
//
|
//
|
||||||
PageTableCount = (PMMPDE)MiAddressToPte(MmPagedPoolInfo.LastPteForPagedPool) -
|
PageTableCount = (PMMPDE)MiAddressToPte(MmPagedPoolInfo.LastPteForPagedPool) -
|
||||||
MmPagedPoolInfo.NextPdeForPagedPoolExpansion +
|
MmPagedPoolInfo.NextPdeForPagedPoolExpansion +
|
||||||
1;
|
1;
|
||||||
ASSERT(PageTableCount < i);
|
ASSERT(PageTableCount < i);
|
||||||
|
@ -454,30 +453,30 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
//
|
//
|
||||||
PageTableCount = i;
|
PageTableCount = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the template PDE we'll use to expand
|
// Get the template PDE we'll use to expand
|
||||||
//
|
//
|
||||||
TempPde = ValidKernelPde;
|
TempPde = ValidKernelPde;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the first PTE in expansion space
|
// Get the first PTE in expansion space
|
||||||
//
|
//
|
||||||
PointerPde = MmPagedPoolInfo.NextPdeForPagedPoolExpansion;
|
PointerPde = MmPagedPoolInfo.NextPdeForPagedPoolExpansion;
|
||||||
BaseVa = MiPdeToAddress(PointerPde);
|
BaseVa = MiPdeToAddress(PointerPde);
|
||||||
BaseVaStart = BaseVa;
|
BaseVaStart = BaseVa;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Lock the PFN database and loop pages
|
// Lock the PFN database and loop pages
|
||||||
//
|
//
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// It should not already be valid
|
// It should not already be valid
|
||||||
//
|
//
|
||||||
ASSERT(PointerPde->u.Hard.Valid == 0);
|
ASSERT(PointerPde->u.Hard.Valid == 0);
|
||||||
|
|
||||||
/* Request a page */
|
/* Request a page */
|
||||||
MI_SET_USAGE(MI_USAGE_PAGED_POOL);
|
MI_SET_USAGE(MI_USAGE_PAGED_POOL);
|
||||||
MI_SET_PROCESS2("Kernel");
|
MI_SET_PROCESS2("Kernel");
|
||||||
|
@ -491,15 +490,15 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
// Save it into our double-buffered system page directory
|
// Save it into our double-buffered system page directory
|
||||||
//
|
//
|
||||||
MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)] = TempPde;
|
MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)] = TempPde;
|
||||||
|
|
||||||
/* Initialize the PFN */
|
/* Initialize the PFN */
|
||||||
MiInitializePfnForOtherProcess(PageFrameNumber,
|
MiInitializePfnForOtherProcess(PageFrameNumber,
|
||||||
(PMMPTE)PointerPde,
|
(PMMPTE)PointerPde,
|
||||||
MmSystemPageDirectory[(PointerPde - MiAddressToPde(NULL)) / PDE_COUNT]);
|
MmSystemPageDirectory[(PointerPde - MiAddressToPde(NULL)) / PDE_COUNT]);
|
||||||
|
|
||||||
/* Write the actual PDE now */
|
/* Write the actual PDE now */
|
||||||
MI_WRITE_VALID_PDE(PointerPde, TempPde);
|
MI_WRITE_VALID_PDE(PointerPde, TempPde);
|
||||||
#endif
|
#endif
|
||||||
//
|
//
|
||||||
// Move on to the next expansion address
|
// Move on to the next expansion address
|
||||||
//
|
//
|
||||||
|
@ -507,12 +506,12 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
BaseVa = (PVOID)((ULONG_PTR)BaseVa + PAGE_SIZE);
|
BaseVa = (PVOID)((ULONG_PTR)BaseVa + PAGE_SIZE);
|
||||||
i--;
|
i--;
|
||||||
} while (i > 0);
|
} while (i > 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the PFN database lock
|
// Release the PFN database lock
|
||||||
//
|
//
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
//
|
//
|
||||||
// These pages are now available, clear their availablity bits
|
// These pages are now available, clear their availablity bits
|
||||||
//
|
//
|
||||||
|
@ -522,24 +521,24 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
RtlClearBits(MmPagedPoolInfo.PagedPoolAllocationMap,
|
RtlClearBits(MmPagedPoolInfo.PagedPoolAllocationMap,
|
||||||
EndAllocation,
|
EndAllocation,
|
||||||
PageTableCount * PTE_COUNT);
|
PageTableCount * PTE_COUNT);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update the next expansion location
|
// Update the next expansion location
|
||||||
//
|
//
|
||||||
MmPagedPoolInfo.NextPdeForPagedPoolExpansion += PageTableCount;
|
MmPagedPoolInfo.NextPdeForPagedPoolExpansion += PageTableCount;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Zero out the newly available memory
|
// Zero out the newly available memory
|
||||||
//
|
//
|
||||||
RtlZeroMemory(BaseVaStart, PageTableCount * PAGE_SIZE);
|
RtlZeroMemory(BaseVaStart, PageTableCount * PAGE_SIZE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now try consuming the pages again
|
// Now try consuming the pages again
|
||||||
//
|
//
|
||||||
i = RtlFindClearBitsAndSet(MmPagedPoolInfo.PagedPoolAllocationMap,
|
i = RtlFindClearBitsAndSet(MmPagedPoolInfo.PagedPoolAllocationMap,
|
||||||
SizeInPages,
|
SizeInPages,
|
||||||
0);
|
0);
|
||||||
if (i == 0xFFFFFFFF)
|
if (i == 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Out of memory!
|
// Out of memory!
|
||||||
|
@ -549,37 +548,37 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update the pool hint if the request was just one page
|
// Update the pool hint if the request was just one page
|
||||||
//
|
//
|
||||||
if (SizeInPages == 1) MmPagedPoolInfo.PagedPoolHint = i + 1;
|
if (SizeInPages == 1) MmPagedPoolInfo.PagedPoolHint = i + 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update the end bitmap so we know the bounds of this allocation when
|
// Update the end bitmap so we know the bounds of this allocation when
|
||||||
// the time comes to free it
|
// the time comes to free it
|
||||||
//
|
//
|
||||||
EndAllocation = i + SizeInPages - 1;
|
EndAllocation = i + SizeInPages - 1;
|
||||||
RtlSetBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, EndAllocation);
|
RtlSetBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, EndAllocation);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now we can release the lock (it mainly protects the bitmap)
|
// Now we can release the lock (it mainly protects the bitmap)
|
||||||
//
|
//
|
||||||
KeReleaseGuardedMutex(&MmPagedPoolMutex);
|
KeReleaseGuardedMutex(&MmPagedPoolMutex);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now figure out where this allocation starts
|
// Now figure out where this allocation starts
|
||||||
//
|
//
|
||||||
BaseVa = (PVOID)((ULONG_PTR)MmPagedPoolStart + (i << PAGE_SHIFT));
|
BaseVa = (PVOID)((ULONG_PTR)MmPagedPoolStart + (i << PAGE_SHIFT));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Flush the TLB
|
// Flush the TLB
|
||||||
//
|
//
|
||||||
KeFlushEntireTb(TRUE, TRUE);
|
KeFlushEntireTb(TRUE, TRUE);
|
||||||
|
|
||||||
/* Setup a demand-zero writable PTE */
|
/* Setup a demand-zero writable PTE */
|
||||||
MI_MAKE_SOFTWARE_PTE(&TempPte, MM_READWRITE);
|
MI_MAKE_SOFTWARE_PTE(&TempPte, MM_READWRITE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Find the first and last PTE, then loop them all
|
// Find the first and last PTE, then loop them all
|
||||||
//
|
//
|
||||||
|
@ -592,25 +591,25 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
//
|
//
|
||||||
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
||||||
} while (++PointerPte < StartPte);
|
} while (++PointerPte < StartPte);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return the allocation address to the caller
|
// Return the allocation address to the caller
|
||||||
//
|
//
|
||||||
return BaseVa;
|
return BaseVa;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocations of less than 4 pages go into their individual buckets
|
// Allocations of less than 4 pages go into their individual buckets
|
||||||
//
|
//
|
||||||
i = SizeInPages - 1;
|
i = SizeInPages - 1;
|
||||||
if (i >= MI_MAX_FREE_PAGE_LISTS) i = MI_MAX_FREE_PAGE_LISTS - 1;
|
if (i >= MI_MAX_FREE_PAGE_LISTS) i = MI_MAX_FREE_PAGE_LISTS - 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop through all the free page lists based on the page index
|
// Loop through all the free page lists based on the page index
|
||||||
//
|
//
|
||||||
NextHead = &MmNonPagedPoolFreeListHead[i];
|
NextHead = &MmNonPagedPoolFreeListHead[i];
|
||||||
LastHead = &MmNonPagedPoolFreeListHead[MI_MAX_FREE_PAGE_LISTS];
|
LastHead = &MmNonPagedPoolFreeListHead[MI_MAX_FREE_PAGE_LISTS];
|
||||||
|
|
||||||
//
|
//
|
||||||
// Acquire the nonpaged pool lock
|
// Acquire the nonpaged pool lock
|
||||||
//
|
//
|
||||||
|
@ -629,7 +628,7 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
/* We need to be able to touch this page, unprotect it */
|
/* We need to be able to touch this page, unprotect it */
|
||||||
MiUnProtectFreeNonPagedPool(NextEntry, 0);
|
MiUnProtectFreeNonPagedPool(NextEntry, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Grab the entry and see if it can handle our allocation
|
// Grab the entry and see if it can handle our allocation
|
||||||
//
|
//
|
||||||
|
@ -647,12 +646,12 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
//
|
//
|
||||||
BaseVa = (PVOID)((ULONG_PTR)FreeEntry +
|
BaseVa = (PVOID)((ULONG_PTR)FreeEntry +
|
||||||
(FreeEntry->Size << PAGE_SHIFT));
|
(FreeEntry->Size << PAGE_SHIFT));
|
||||||
|
|
||||||
/* Remove the item from the list, depending if pool is protected */
|
/* Remove the item from the list, depending if pool is protected */
|
||||||
MmProtectFreedNonPagedPool ?
|
MmProtectFreedNonPagedPool ?
|
||||||
MiProtectedPoolRemoveEntryList(&FreeEntry->List) :
|
MiProtectedPoolRemoveEntryList(&FreeEntry->List) :
|
||||||
RemoveEntryList(&FreeEntry->List);
|
RemoveEntryList(&FreeEntry->List);
|
||||||
|
|
||||||
//
|
//
|
||||||
// However, check if its' still got space left
|
// However, check if its' still got space left
|
||||||
//
|
//
|
||||||
|
@ -666,7 +665,7 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
MmProtectFreedNonPagedPool ?
|
MmProtectFreedNonPagedPool ?
|
||||||
MiProtectedPoolInsertList(&MmNonPagedPoolFreeListHead[i], &FreeEntry->List, TRUE) :
|
MiProtectedPoolInsertList(&MmNonPagedPoolFreeListHead[i], &FreeEntry->List, TRUE) :
|
||||||
InsertTailList(&MmNonPagedPoolFreeListHead[i], &FreeEntry->List);
|
InsertTailList(&MmNonPagedPoolFreeListHead[i], &FreeEntry->List);
|
||||||
|
|
||||||
/* Is freed non paged pool protected? */
|
/* Is freed non paged pool protected? */
|
||||||
if (MmProtectFreedNonPagedPool)
|
if (MmProtectFreedNonPagedPool)
|
||||||
{
|
{
|
||||||
|
@ -674,28 +673,28 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
|
MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Grab the PTE for this allocation
|
// Grab the PTE for this allocation
|
||||||
//
|
//
|
||||||
PointerPte = MiAddressToPte(BaseVa);
|
PointerPte = MiAddressToPte(BaseVa);
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 1);
|
ASSERT(PointerPte->u.Hard.Valid == 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Grab the PFN NextEntry and index
|
// Grab the PFN NextEntry and index
|
||||||
//
|
//
|
||||||
Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
|
Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now mark it as the beginning of an allocation
|
// Now mark it as the beginning of an allocation
|
||||||
//
|
//
|
||||||
ASSERT(Pfn1->u3.e1.StartOfAllocation == 0);
|
ASSERT(Pfn1->u3.e1.StartOfAllocation == 0);
|
||||||
Pfn1->u3.e1.StartOfAllocation = 1;
|
Pfn1->u3.e1.StartOfAllocation = 1;
|
||||||
|
|
||||||
/* Mark it as special pool if needed */
|
/* Mark it as special pool if needed */
|
||||||
ASSERT(Pfn1->u4.VerifierAllocation == 0);
|
ASSERT(Pfn1->u4.VerifierAllocation == 0);
|
||||||
if (PoolType & 64) Pfn1->u4.VerifierAllocation = 1;
|
if (PoolType & 64) Pfn1->u4.VerifierAllocation = 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if the allocation is larger than one page
|
// Check if the allocation is larger than one page
|
||||||
//
|
//
|
||||||
|
@ -708,25 +707,25 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 1);
|
ASSERT(PointerPte->u.Hard.Valid == 1);
|
||||||
Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
|
Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Mark this PFN as the last (might be the same as the first)
|
// Mark this PFN as the last (might be the same as the first)
|
||||||
//
|
//
|
||||||
ASSERT(Pfn1->u3.e1.EndOfAllocation == 0);
|
ASSERT(Pfn1->u3.e1.EndOfAllocation == 0);
|
||||||
Pfn1->u3.e1.EndOfAllocation = 1;
|
Pfn1->u3.e1.EndOfAllocation = 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the nonpaged pool lock, and return the allocation
|
// Release the nonpaged pool lock, and return the allocation
|
||||||
//
|
//
|
||||||
KeReleaseQueuedSpinLock(LockQueueMmNonPagedPoolLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueueMmNonPagedPoolLock, OldIrql);
|
||||||
return BaseVa;
|
return BaseVa;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Try the next free page entry
|
// Try the next free page entry
|
||||||
//
|
//
|
||||||
NextEntry = FreeEntry->List.Flink;
|
NextEntry = FreeEntry->List.Flink;
|
||||||
|
|
||||||
/* Is freed non paged pool protected? */
|
/* Is freed non paged pool protected? */
|
||||||
if (MmProtectFreedNonPagedPool)
|
if (MmProtectFreedNonPagedPool)
|
||||||
{
|
{
|
||||||
|
@ -735,7 +734,7 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (++NextHead < LastHead);
|
} while (++NextHead < LastHead);
|
||||||
|
|
||||||
//
|
//
|
||||||
// If we got here, we're out of space.
|
// If we got here, we're out of space.
|
||||||
// Start by releasing the lock
|
// Start by releasing the lock
|
||||||
|
@ -755,18 +754,18 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
DPRINT1("Out of NP Expansion Pool\n");
|
DPRINT1("Out of NP Expansion Pool\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Acquire the pool lock now
|
// Acquire the pool lock now
|
||||||
//
|
//
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueMmNonPagedPoolLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueueMmNonPagedPoolLock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Lock the PFN database too
|
// Lock the PFN database too
|
||||||
//
|
//
|
||||||
LockQueue = &KeGetCurrentPrcb()->LockQueue[LockQueuePfnLock];
|
LockQueue = &KeGetCurrentPrcb()->LockQueue[LockQueuePfnLock];
|
||||||
KeAcquireQueuedSpinLockAtDpcLevel(LockQueue);
|
KeAcquireQueuedSpinLockAtDpcLevel(LockQueue);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop the pages
|
// Loop the pages
|
||||||
//
|
//
|
||||||
|
@ -777,7 +776,7 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
MI_SET_USAGE(MI_USAGE_PAGED_POOL);
|
MI_SET_USAGE(MI_USAGE_PAGED_POOL);
|
||||||
MI_SET_PROCESS2("Kernel");
|
MI_SET_PROCESS2("Kernel");
|
||||||
PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
|
PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
|
||||||
|
|
||||||
/* Get the PFN entry for it and fill it out */
|
/* Get the PFN entry for it and fill it out */
|
||||||
Pfn1 = MiGetPfnEntry(PageFrameNumber);
|
Pfn1 = MiGetPfnEntry(PageFrameNumber);
|
||||||
Pfn1->u3.e2.ReferenceCount = 1;
|
Pfn1->u3.e2.ReferenceCount = 1;
|
||||||
|
@ -785,33 +784,33 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
Pfn1->PteAddress = PointerPte;
|
Pfn1->PteAddress = PointerPte;
|
||||||
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
||||||
Pfn1->u4.VerifierAllocation = 0;
|
Pfn1->u4.VerifierAllocation = 0;
|
||||||
|
|
||||||
/* Write the PTE for it */
|
/* Write the PTE for it */
|
||||||
TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
|
TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
|
||||||
MI_WRITE_VALID_PTE(PointerPte++, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte++, TempPte);
|
||||||
} while (--SizeInPages > 0);
|
} while (--SizeInPages > 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// This is the last page
|
// This is the last page
|
||||||
//
|
//
|
||||||
Pfn1->u3.e1.EndOfAllocation = 1;
|
Pfn1->u3.e1.EndOfAllocation = 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the first page and mark it as such
|
// Get the first page and mark it as such
|
||||||
//
|
//
|
||||||
Pfn1 = MiGetPfnEntry(StartPte->u.Hard.PageFrameNumber);
|
Pfn1 = MiGetPfnEntry(StartPte->u.Hard.PageFrameNumber);
|
||||||
Pfn1->u3.e1.StartOfAllocation = 1;
|
Pfn1->u3.e1.StartOfAllocation = 1;
|
||||||
|
|
||||||
/* Mark it as a verifier allocation if needed */
|
/* Mark it as a verifier allocation if needed */
|
||||||
ASSERT(Pfn1->u4.VerifierAllocation == 0);
|
ASSERT(Pfn1->u4.VerifierAllocation == 0);
|
||||||
if (PoolType & 64) Pfn1->u4.VerifierAllocation = 1;
|
if (PoolType & 64) Pfn1->u4.VerifierAllocation = 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the PFN and nonpaged pool lock
|
// Release the PFN and nonpaged pool lock
|
||||||
//
|
//
|
||||||
KeReleaseQueuedSpinLockFromDpcLevel(LockQueue);
|
KeReleaseQueuedSpinLockFromDpcLevel(LockQueue);
|
||||||
KeReleaseQueuedSpinLock(LockQueueMmNonPagedPoolLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueueMmNonPagedPoolLock, OldIrql);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return the address
|
// Return the address
|
||||||
//
|
//
|
||||||
|
@ -828,7 +827,7 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PMMFREE_POOL_ENTRY FreeEntry, NextEntry, LastEntry;
|
PMMFREE_POOL_ENTRY FreeEntry, NextEntry, LastEntry;
|
||||||
ULONG i, End;
|
ULONG i, End;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle paged pool
|
// Handle paged pool
|
||||||
//
|
//
|
||||||
|
@ -840,56 +839,56 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
//
|
//
|
||||||
i = ((ULONG_PTR)StartingVa - (ULONG_PTR)MmPagedPoolStart) >> PAGE_SHIFT;
|
i = ((ULONG_PTR)StartingVa - (ULONG_PTR)MmPagedPoolStart) >> PAGE_SHIFT;
|
||||||
End = i;
|
End = i;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now use the end bitmap to scan until we find a set bit, meaning that
|
// Now use the end bitmap to scan until we find a set bit, meaning that
|
||||||
// this allocation finishes here
|
// this allocation finishes here
|
||||||
//
|
//
|
||||||
while (!RtlTestBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, End)) End++;
|
while (!RtlTestBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, End)) End++;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now calculate the total number of pages this allocation spans
|
// Now calculate the total number of pages this allocation spans
|
||||||
//
|
//
|
||||||
NumberOfPages = End - i + 1;
|
NumberOfPages = End - i + 1;
|
||||||
|
|
||||||
/* Delete the actual pages */
|
/* Delete the actual pages */
|
||||||
PointerPte = MmPagedPoolInfo.FirstPteForPagedPool + i;
|
PointerPte = MmPagedPoolInfo.FirstPteForPagedPool + i;
|
||||||
FreePages = MiDeleteSystemPageableVm(PointerPte, NumberOfPages, 0, NULL);
|
FreePages = MiDeleteSystemPageableVm(PointerPte, NumberOfPages, 0, NULL);
|
||||||
ASSERT(FreePages == NumberOfPages);
|
ASSERT(FreePages == NumberOfPages);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Acquire the paged pool lock
|
// Acquire the paged pool lock
|
||||||
//
|
//
|
||||||
KeAcquireGuardedMutex(&MmPagedPoolMutex);
|
KeAcquireGuardedMutex(&MmPagedPoolMutex);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Clear the allocation and free bits
|
// Clear the allocation and free bits
|
||||||
//
|
//
|
||||||
RtlClearBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, i);
|
RtlClearBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, i);
|
||||||
RtlClearBits(MmPagedPoolInfo.PagedPoolAllocationMap, i, NumberOfPages);
|
RtlClearBits(MmPagedPoolInfo.PagedPoolAllocationMap, i, NumberOfPages);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update the hint if we need to
|
// Update the hint if we need to
|
||||||
//
|
//
|
||||||
if (i < MmPagedPoolInfo.PagedPoolHint) MmPagedPoolInfo.PagedPoolHint = i;
|
if (i < MmPagedPoolInfo.PagedPoolHint) MmPagedPoolInfo.PagedPoolHint = i;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the lock protecting the bitmaps
|
// Release the lock protecting the bitmaps
|
||||||
//
|
//
|
||||||
KeReleaseGuardedMutex(&MmPagedPoolMutex);
|
KeReleaseGuardedMutex(&MmPagedPoolMutex);
|
||||||
|
|
||||||
//
|
//
|
||||||
// And finally return the number of pages freed
|
// And finally return the number of pages freed
|
||||||
//
|
//
|
||||||
return NumberOfPages;
|
return NumberOfPages;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the first PTE and its corresponding PFN entry
|
// Get the first PTE and its corresponding PFN entry
|
||||||
//
|
//
|
||||||
StartPte = PointerPte = MiAddressToPte(StartingVa);
|
StartPte = PointerPte = MiAddressToPte(StartingVa);
|
||||||
StartPfn = Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
|
StartPfn = Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop until we find the last PTE
|
// Loop until we find the last PTE
|
||||||
//
|
//
|
||||||
|
@ -901,33 +900,33 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
|
Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now we know how many pages we have
|
// Now we know how many pages we have
|
||||||
//
|
//
|
||||||
NumberOfPages = PointerPte - StartPte + 1;
|
NumberOfPages = PointerPte - StartPte + 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Acquire the nonpaged pool lock
|
// Acquire the nonpaged pool lock
|
||||||
//
|
//
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueMmNonPagedPoolLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueueMmNonPagedPoolLock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Mark the first and last PTEs as not part of an allocation anymore
|
// Mark the first and last PTEs as not part of an allocation anymore
|
||||||
//
|
//
|
||||||
StartPfn->u3.e1.StartOfAllocation = 0;
|
StartPfn->u3.e1.StartOfAllocation = 0;
|
||||||
Pfn1->u3.e1.EndOfAllocation = 0;
|
Pfn1->u3.e1.EndOfAllocation = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Assume we will free as many pages as the allocation was
|
// Assume we will free as many pages as the allocation was
|
||||||
//
|
//
|
||||||
FreePages = NumberOfPages;
|
FreePages = NumberOfPages;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Peek one page past the end of the allocation
|
// Peek one page past the end of the allocation
|
||||||
//
|
//
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Guard against going past initial nonpaged pool
|
// Guard against going past initial nonpaged pool
|
||||||
//
|
//
|
||||||
|
@ -942,16 +941,16 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
{
|
{
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
ASSERT((ULONG_PTR)StartingVa + NumberOfPages <= (ULONG_PTR)MmNonPagedPoolEnd);
|
ASSERT((ULONG_PTR)StartingVa + NumberOfPages <= (ULONG_PTR)MmNonPagedPoolEnd);
|
||||||
|
|
||||||
/* Check if protected pool is enabled */
|
/* Check if protected pool is enabled */
|
||||||
if (MmProtectFreedNonPagedPool)
|
if (MmProtectFreedNonPagedPool)
|
||||||
{
|
{
|
||||||
/* The freed block will be merged, it must be made accessible */
|
/* The freed block will be merged, it must be made accessible */
|
||||||
MiUnProtectFreeNonPagedPool(MiPteToAddress(PointerPte), 0);
|
MiUnProtectFreeNonPagedPool(MiPteToAddress(PointerPte), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Otherwise, our entire allocation must've fit within the initial non
|
// Otherwise, our entire allocation must've fit within the initial non
|
||||||
// paged pool, or the expansion nonpaged pool, so get the PFN entry of
|
// paged pool, or the expansion nonpaged pool, so get the PFN entry of
|
||||||
// the next allocation
|
// the next allocation
|
||||||
//
|
//
|
||||||
|
@ -960,7 +959,7 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
//
|
//
|
||||||
// It's either expansion or initial: get the PFN entry
|
// It's either expansion or initial: get the PFN entry
|
||||||
//
|
//
|
||||||
Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
|
Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -970,9 +969,9 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
//
|
//
|
||||||
Pfn1 = NULL;
|
Pfn1 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this allocation actually exists
|
// Check if this allocation actually exists
|
||||||
//
|
//
|
||||||
|
@ -985,21 +984,21 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
(NumberOfPages << PAGE_SHIFT));
|
(NumberOfPages << PAGE_SHIFT));
|
||||||
ASSERT(FreeEntry->Signature == MM_FREE_POOL_SIGNATURE);
|
ASSERT(FreeEntry->Signature == MM_FREE_POOL_SIGNATURE);
|
||||||
ASSERT(FreeEntry->Owner == FreeEntry);
|
ASSERT(FreeEntry->Owner == FreeEntry);
|
||||||
|
|
||||||
/* Consume this entry's pages */
|
/* Consume this entry's pages */
|
||||||
FreePages += FreeEntry->Size;
|
FreePages += FreeEntry->Size;
|
||||||
|
|
||||||
/* Remove the item from the list, depending if pool is protected */
|
/* Remove the item from the list, depending if pool is protected */
|
||||||
MmProtectFreedNonPagedPool ?
|
MmProtectFreedNonPagedPool ?
|
||||||
MiProtectedPoolRemoveEntryList(&FreeEntry->List) :
|
MiProtectedPoolRemoveEntryList(&FreeEntry->List) :
|
||||||
RemoveEntryList(&FreeEntry->List);
|
RemoveEntryList(&FreeEntry->List);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now get the official free entry we'll create for the caller's allocation
|
// Now get the official free entry we'll create for the caller's allocation
|
||||||
//
|
//
|
||||||
FreeEntry = StartingVa;
|
FreeEntry = StartingVa;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if the our allocation is the very first page
|
// Check if the our allocation is the very first page
|
||||||
//
|
//
|
||||||
|
@ -1016,14 +1015,14 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
// Otherwise, get the PTE for the page right before our allocation
|
// Otherwise, get the PTE for the page right before our allocation
|
||||||
//
|
//
|
||||||
PointerPte -= NumberOfPages + 1;
|
PointerPte -= NumberOfPages + 1;
|
||||||
|
|
||||||
/* Check if protected pool is enabled */
|
/* Check if protected pool is enabled */
|
||||||
if (MmProtectFreedNonPagedPool)
|
if (MmProtectFreedNonPagedPool)
|
||||||
{
|
{
|
||||||
/* The freed block will be merged, it must be made accessible */
|
/* The freed block will be merged, it must be made accessible */
|
||||||
MiUnProtectFreeNonPagedPool(MiPteToAddress(PointerPte), 0);
|
MiUnProtectFreeNonPagedPool(MiPteToAddress(PointerPte), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if this is valid pool, or a guard page */
|
/* Check if this is valid pool, or a guard page */
|
||||||
if (PointerPte->u.Hard.Valid == 1)
|
if (PointerPte->u.Hard.Valid == 1)
|
||||||
{
|
{
|
||||||
|
@ -1040,7 +1039,7 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
Pfn1 = NULL;
|
Pfn1 = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if there is a valid PFN entry for the page before the allocation
|
// Check if there is a valid PFN entry for the page before the allocation
|
||||||
// and then check if this page was actually the end of an allocation.
|
// and then check if this page was actually the end of an allocation.
|
||||||
|
@ -1054,14 +1053,14 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
FreeEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)StartingVa - PAGE_SIZE);
|
FreeEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)StartingVa - PAGE_SIZE);
|
||||||
ASSERT(FreeEntry->Signature == MM_FREE_POOL_SIGNATURE);
|
ASSERT(FreeEntry->Signature == MM_FREE_POOL_SIGNATURE);
|
||||||
FreeEntry = FreeEntry->Owner;
|
FreeEntry = FreeEntry->Owner;
|
||||||
|
|
||||||
/* Check if protected pool is enabled */
|
/* Check if protected pool is enabled */
|
||||||
if (MmProtectFreedNonPagedPool)
|
if (MmProtectFreedNonPagedPool)
|
||||||
{
|
{
|
||||||
/* The freed block will be merged, it must be made accessible */
|
/* The freed block will be merged, it must be made accessible */
|
||||||
MiUnProtectFreeNonPagedPool(FreeEntry, 0);
|
MiUnProtectFreeNonPagedPool(FreeEntry, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if the entry is small enough to be indexed on a free list
|
// Check if the entry is small enough to be indexed on a free list
|
||||||
// If it is, we'll want to re-insert it, since we're about to
|
// If it is, we'll want to re-insert it, since we're about to
|
||||||
|
@ -1073,18 +1072,18 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
MmProtectFreedNonPagedPool ?
|
MmProtectFreedNonPagedPool ?
|
||||||
MiProtectedPoolRemoveEntryList(&FreeEntry->List) :
|
MiProtectedPoolRemoveEntryList(&FreeEntry->List) :
|
||||||
RemoveEntryList(&FreeEntry->List);
|
RemoveEntryList(&FreeEntry->List);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update its size
|
// Update its size
|
||||||
//
|
//
|
||||||
FreeEntry->Size += FreePages;
|
FreeEntry->Size += FreePages;
|
||||||
|
|
||||||
//
|
//
|
||||||
// And now find the new appropriate list to place it in
|
// And now find the new appropriate list to place it in
|
||||||
//
|
//
|
||||||
i = (ULONG)(FreeEntry->Size - 1);
|
i = (ULONG)(FreeEntry->Size - 1);
|
||||||
if (i >= MI_MAX_FREE_PAGE_LISTS) i = MI_MAX_FREE_PAGE_LISTS - 1;
|
if (i >= MI_MAX_FREE_PAGE_LISTS) i = MI_MAX_FREE_PAGE_LISTS - 1;
|
||||||
|
|
||||||
/* Insert the entry into the free list head, check for prot. pool */
|
/* Insert the entry into the free list head, check for prot. pool */
|
||||||
MmProtectFreedNonPagedPool ?
|
MmProtectFreedNonPagedPool ?
|
||||||
MiProtectedPoolInsertList(&MmNonPagedPoolFreeListHead[i], &FreeEntry->List, TRUE) :
|
MiProtectedPoolInsertList(&MmNonPagedPoolFreeListHead[i], &FreeEntry->List, TRUE) :
|
||||||
|
@ -1098,7 +1097,7 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
FreeEntry->Size += FreePages;
|
FreeEntry->Size += FreePages;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we were unable to do any compaction, and we'll stick with this
|
// Check if we were unable to do any compaction, and we'll stick with this
|
||||||
//
|
//
|
||||||
|
@ -1109,30 +1108,30 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
// pages, at best we have our pages plus whatever entry came after us
|
// pages, at best we have our pages plus whatever entry came after us
|
||||||
//
|
//
|
||||||
FreeEntry->Size = FreePages;
|
FreeEntry->Size = FreePages;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Find the appropriate list we should be on
|
// Find the appropriate list we should be on
|
||||||
//
|
//
|
||||||
i = FreeEntry->Size - 1;
|
i = FreeEntry->Size - 1;
|
||||||
if (i >= MI_MAX_FREE_PAGE_LISTS) i = MI_MAX_FREE_PAGE_LISTS - 1;
|
if (i >= MI_MAX_FREE_PAGE_LISTS) i = MI_MAX_FREE_PAGE_LISTS - 1;
|
||||||
|
|
||||||
/* Insert the entry into the free list head, check for prot. pool */
|
/* Insert the entry into the free list head, check for prot. pool */
|
||||||
MmProtectFreedNonPagedPool ?
|
MmProtectFreedNonPagedPool ?
|
||||||
MiProtectedPoolInsertList(&MmNonPagedPoolFreeListHead[i], &FreeEntry->List, TRUE) :
|
MiProtectedPoolInsertList(&MmNonPagedPoolFreeListHead[i], &FreeEntry->List, TRUE) :
|
||||||
InsertTailList(&MmNonPagedPoolFreeListHead[i], &FreeEntry->List);
|
InsertTailList(&MmNonPagedPoolFreeListHead[i], &FreeEntry->List);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Just a sanity check
|
// Just a sanity check
|
||||||
//
|
//
|
||||||
ASSERT(FreePages != 0);
|
ASSERT(FreePages != 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get all the pages between our allocation and its end. These will all now
|
// Get all the pages between our allocation and its end. These will all now
|
||||||
// become free page chunks.
|
// become free page chunks.
|
||||||
//
|
//
|
||||||
NextEntry = StartingVa;
|
NextEntry = StartingVa;
|
||||||
LastEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + (FreePages << PAGE_SHIFT));
|
LastEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + (FreePages << PAGE_SHIFT));
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -1142,14 +1141,14 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
NextEntry->Signature = MM_FREE_POOL_SIGNATURE;
|
NextEntry->Signature = MM_FREE_POOL_SIGNATURE;
|
||||||
NextEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + PAGE_SIZE);
|
NextEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + PAGE_SIZE);
|
||||||
} while (NextEntry != LastEntry);
|
} while (NextEntry != LastEntry);
|
||||||
|
|
||||||
/* Is freed non paged pool protected? */
|
/* Is freed non paged pool protected? */
|
||||||
if (MmProtectFreedNonPagedPool)
|
if (MmProtectFreedNonPagedPool)
|
||||||
{
|
{
|
||||||
/* Protect the freed pool! */
|
/* Protect the freed pool! */
|
||||||
MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
|
MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// We're done, release the lock and let the caller know how much we freed
|
// We're done, release the lock and let the caller know how much we freed
|
||||||
//
|
//
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::PROCSUP"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -60,11 +59,11 @@ MiCreatePebOrTeb(IN PEPROCESS Process,
|
||||||
LARGE_INTEGER CurrentTime;
|
LARGE_INTEGER CurrentTime;
|
||||||
TABLE_SEARCH_RESULT Result = TableFoundNode;
|
TABLE_SEARCH_RESULT Result = TableFoundNode;
|
||||||
PMMADDRESS_NODE Parent;
|
PMMADDRESS_NODE Parent;
|
||||||
|
|
||||||
/* Allocate a VAD */
|
/* Allocate a VAD */
|
||||||
Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
|
Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
|
||||||
if (!Vad) return STATUS_NO_MEMORY;
|
if (!Vad) return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
/* Setup the primary flags with the size, and make it commited, private, RW */
|
/* Setup the primary flags with the size, and make it commited, private, RW */
|
||||||
Vad->u.LongFlags = 0;
|
Vad->u.LongFlags = 0;
|
||||||
Vad->u.VadFlags.CommitCharge = BYTES_TO_PAGES(Size);
|
Vad->u.VadFlags.CommitCharge = BYTES_TO_PAGES(Size);
|
||||||
|
@ -72,13 +71,13 @@ MiCreatePebOrTeb(IN PEPROCESS Process,
|
||||||
Vad->u.VadFlags.PrivateMemory = TRUE;
|
Vad->u.VadFlags.PrivateMemory = TRUE;
|
||||||
Vad->u.VadFlags.Protection = MM_READWRITE;
|
Vad->u.VadFlags.Protection = MM_READWRITE;
|
||||||
Vad->u.VadFlags.NoChange = TRUE;
|
Vad->u.VadFlags.NoChange = TRUE;
|
||||||
|
|
||||||
/* Setup the secondary flags to make it a secured, writable, long VAD */
|
/* Setup the secondary flags to make it a secured, writable, long VAD */
|
||||||
Vad->u2.LongFlags2 = 0;
|
Vad->u2.LongFlags2 = 0;
|
||||||
Vad->u2.VadFlags2.OneSecured = TRUE;
|
Vad->u2.VadFlags2.OneSecured = TRUE;
|
||||||
Vad->u2.VadFlags2.LongVad = TRUE;
|
Vad->u2.VadFlags2.LongVad = TRUE;
|
||||||
Vad->u2.VadFlags2.ReadOnly = FALSE;
|
Vad->u2.VadFlags2.ReadOnly = FALSE;
|
||||||
|
|
||||||
/* Lock the process address space */
|
/* Lock the process address space */
|
||||||
KeAcquireGuardedMutex(&Process->AddressCreationLock);
|
KeAcquireGuardedMutex(&Process->AddressCreationLock);
|
||||||
|
|
||||||
|
@ -120,23 +119,23 @@ MiCreatePebOrTeb(IN PEPROCESS Process,
|
||||||
/* Bail out, if still nothing free was found */
|
/* Bail out, if still nothing free was found */
|
||||||
if (Result == TableFoundNode) return STATUS_NO_MEMORY;
|
if (Result == TableFoundNode) return STATUS_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Validate that it came from the VAD ranges */
|
/* Validate that it came from the VAD ranges */
|
||||||
ASSERT(*Base >= (ULONG_PTR)MI_LOWEST_VAD_ADDRESS);
|
ASSERT(*Base >= (ULONG_PTR)MI_LOWEST_VAD_ADDRESS);
|
||||||
|
|
||||||
/* Build the rest of the VAD now */
|
/* Build the rest of the VAD now */
|
||||||
Vad->StartingVpn = (*Base) >> PAGE_SHIFT;
|
Vad->StartingVpn = (*Base) >> PAGE_SHIFT;
|
||||||
Vad->EndingVpn = ((*Base) + Size - 1) >> PAGE_SHIFT;
|
Vad->EndingVpn = ((*Base) + Size - 1) >> PAGE_SHIFT;
|
||||||
Vad->u3.Secured.StartVpn = *Base;
|
Vad->u3.Secured.StartVpn = *Base;
|
||||||
Vad->u3.Secured.EndVpn = (Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1);
|
Vad->u3.Secured.EndVpn = (Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1);
|
||||||
Vad->u1.Parent = NULL;
|
Vad->u1.Parent = NULL;
|
||||||
|
|
||||||
/* FIXME: Should setup VAD bitmap */
|
/* FIXME: Should setup VAD bitmap */
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
/* Pretend as if we own the working set */
|
/* Pretend as if we own the working set */
|
||||||
MiLockProcessWorkingSet(Process, Thread);
|
MiLockProcessWorkingSet(Process, Thread);
|
||||||
|
|
||||||
/* Insert the VAD */
|
/* Insert the VAD */
|
||||||
ASSERT(Vad->EndingVpn >= Vad->StartingVpn);
|
ASSERT(Vad->EndingVpn >= Vad->StartingVpn);
|
||||||
Process->VadRoot.NodeHint = Vad;
|
Process->VadRoot.NodeHint = Vad;
|
||||||
|
@ -166,20 +165,20 @@ MmDeleteTeb(IN PEPROCESS Process,
|
||||||
PMMVAD Vad;
|
PMMVAD Vad;
|
||||||
PMM_AVL_TABLE VadTree = &Process->VadRoot;
|
PMM_AVL_TABLE VadTree = &Process->VadRoot;
|
||||||
DPRINT("Deleting TEB: %p in %16s\n", Teb, Process->ImageFileName);
|
DPRINT("Deleting TEB: %p in %16s\n", Teb, Process->ImageFileName);
|
||||||
|
|
||||||
/* TEB is one page */
|
/* TEB is one page */
|
||||||
TebEnd = (ULONG_PTR)Teb + ROUND_TO_PAGES(sizeof(TEB)) - 1;
|
TebEnd = (ULONG_PTR)Teb + ROUND_TO_PAGES(sizeof(TEB)) - 1;
|
||||||
|
|
||||||
/* Attach to the process */
|
/* Attach to the process */
|
||||||
KeAttachProcess(&Process->Pcb);
|
KeAttachProcess(&Process->Pcb);
|
||||||
|
|
||||||
/* Lock the process address space */
|
/* Lock the process address space */
|
||||||
KeAcquireGuardedMutex(&Process->AddressCreationLock);
|
KeAcquireGuardedMutex(&Process->AddressCreationLock);
|
||||||
|
|
||||||
/* Find the VAD, make sure it's a TEB VAD */
|
/* Find the VAD, make sure it's a TEB VAD */
|
||||||
Vad = MiLocateAddress(Teb);
|
Vad = MiLocateAddress(Teb);
|
||||||
DPRINT("Removing node for VAD: %lx %lx\n", Vad->StartingVpn, Vad->EndingVpn);
|
DPRINT("Removing node for VAD: %lx %lx\n", Vad->StartingVpn, Vad->EndingVpn);
|
||||||
ASSERT(Vad != NULL);
|
ASSERT(Vad != NULL);
|
||||||
if (Vad->StartingVpn != ((ULONG_PTR)Teb >> PAGE_SHIFT))
|
if (Vad->StartingVpn != ((ULONG_PTR)Teb >> PAGE_SHIFT))
|
||||||
{
|
{
|
||||||
/* Bug in the AVL code? */
|
/* Bug in the AVL code? */
|
||||||
|
@ -200,17 +199,17 @@ MmDeleteTeb(IN PEPROCESS Process,
|
||||||
/* Remove this VAD from the tree */
|
/* Remove this VAD from the tree */
|
||||||
ASSERT(VadTree->NumberGenericTableElements >= 1);
|
ASSERT(VadTree->NumberGenericTableElements >= 1);
|
||||||
MiRemoveNode((PMMADDRESS_NODE)Vad, VadTree);
|
MiRemoveNode((PMMADDRESS_NODE)Vad, VadTree);
|
||||||
|
|
||||||
/* Release the working set */
|
/* Release the working set */
|
||||||
MiUnlockProcessWorkingSet(Process, Thread);
|
MiUnlockProcessWorkingSet(Process, Thread);
|
||||||
|
|
||||||
/* Remove the VAD */
|
/* Remove the VAD */
|
||||||
ExFreePool(Vad);
|
ExFreePool(Vad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the address space lock */
|
/* Release the address space lock */
|
||||||
KeReleaseGuardedMutex(&Process->AddressCreationLock);
|
KeReleaseGuardedMutex(&Process->AddressCreationLock);
|
||||||
|
|
||||||
/* Detach */
|
/* Detach */
|
||||||
KeDetachProcess();
|
KeDetachProcess();
|
||||||
}
|
}
|
||||||
|
@ -225,22 +224,22 @@ MmDeleteKernelStack(IN PVOID StackBase,
|
||||||
PMMPFN Pfn1;//, Pfn2;
|
PMMPFN Pfn1;//, Pfn2;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
|
||||||
//
|
//
|
||||||
// This should be the guard page, so decrement by one
|
// This should be the guard page, so decrement by one
|
||||||
//
|
//
|
||||||
PointerPte = MiAddressToPte(StackBase);
|
PointerPte = MiAddressToPte(StackBase);
|
||||||
PointerPte--;
|
PointerPte--;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Calculate pages used
|
// Calculate pages used
|
||||||
//
|
//
|
||||||
StackPages = BYTES_TO_PAGES(GuiStack ?
|
StackPages = BYTES_TO_PAGES(GuiStack ?
|
||||||
KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE);
|
KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE);
|
||||||
|
|
||||||
/* Acquire the PFN lock */
|
/* Acquire the PFN lock */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop them
|
// Loop them
|
||||||
//
|
//
|
||||||
|
@ -258,28 +257,28 @@ MmDeleteKernelStack(IN PVOID StackBase,
|
||||||
/* Now get the page of the page table mapping it */
|
/* Now get the page of the page table mapping it */
|
||||||
PageTableFrameNumber = Pfn1->u4.PteFrame;
|
PageTableFrameNumber = Pfn1->u4.PteFrame;
|
||||||
Pfn2 = MiGetPfnEntry(PageTableFrameNumber);
|
Pfn2 = MiGetPfnEntry(PageTableFrameNumber);
|
||||||
|
|
||||||
/* Remove a shared reference, since the page is going away */
|
/* Remove a shared reference, since the page is going away */
|
||||||
MiDecrementShareCount(Pfn2, PageTableFrameNumber);
|
MiDecrementShareCount(Pfn2, PageTableFrameNumber);
|
||||||
#endif
|
#endif
|
||||||
/* Set the special pending delete marker */
|
/* Set the special pending delete marker */
|
||||||
MI_SET_PFN_DELETED(Pfn1);
|
MI_SET_PFN_DELETED(Pfn1);
|
||||||
|
|
||||||
/* And now delete the actual stack page */
|
/* And now delete the actual stack page */
|
||||||
MiDecrementShareCount(Pfn1, PageFrameNumber);
|
MiDecrementShareCount(Pfn1, PageFrameNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Next one
|
// Next one
|
||||||
//
|
//
|
||||||
PointerPte--;
|
PointerPte--;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// We should be at the guard page now
|
// We should be at the guard page now
|
||||||
//
|
//
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 0);
|
ASSERT(PointerPte->u.Hard.Valid == 0);
|
||||||
|
|
||||||
/* Release the PFN lock */
|
/* Release the PFN lock */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
|
@ -301,7 +300,7 @@ MmCreateKernelStack(IN BOOLEAN GuiStack,
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PFN_NUMBER PageFrameIndex;
|
PFN_NUMBER PageFrameIndex;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Calculate pages needed
|
// Calculate pages needed
|
||||||
//
|
//
|
||||||
|
@ -312,7 +311,7 @@ MmCreateKernelStack(IN BOOLEAN GuiStack,
|
||||||
//
|
//
|
||||||
StackPtes = BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE);
|
StackPtes = BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE);
|
||||||
StackPages = BYTES_TO_PAGES(KERNEL_LARGE_STACK_COMMIT);
|
StackPages = BYTES_TO_PAGES(KERNEL_LARGE_STACK_COMMIT);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -322,37 +321,37 @@ MmCreateKernelStack(IN BOOLEAN GuiStack,
|
||||||
StackPtes = BYTES_TO_PAGES(KERNEL_STACK_SIZE);
|
StackPtes = BYTES_TO_PAGES(KERNEL_STACK_SIZE);
|
||||||
StackPages = StackPtes;
|
StackPages = StackPtes;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reserve stack pages, plus a guard page
|
// Reserve stack pages, plus a guard page
|
||||||
//
|
//
|
||||||
StackPte = MiReserveSystemPtes(StackPtes + 1, SystemPteSpace);
|
StackPte = MiReserveSystemPtes(StackPtes + 1, SystemPteSpace);
|
||||||
if (!StackPte) return NULL;
|
if (!StackPte) return NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the stack address
|
// Get the stack address
|
||||||
//
|
//
|
||||||
BaseAddress = MiPteToAddress(StackPte + StackPtes + 1);
|
BaseAddress = MiPteToAddress(StackPte + StackPtes + 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Select the right PTE address where we actually start committing pages
|
// Select the right PTE address where we actually start committing pages
|
||||||
//
|
//
|
||||||
PointerPte = StackPte;
|
PointerPte = StackPte;
|
||||||
if (GuiStack) PointerPte += BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE -
|
if (GuiStack) PointerPte += BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE -
|
||||||
KERNEL_LARGE_STACK_COMMIT);
|
KERNEL_LARGE_STACK_COMMIT);
|
||||||
|
|
||||||
|
|
||||||
/* Setup the temporary invalid PTE */
|
/* Setup the temporary invalid PTE */
|
||||||
MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS);
|
MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS);
|
||||||
|
|
||||||
/* Setup the template stack PTE */
|
/* Setup the template stack PTE */
|
||||||
MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, PointerPte + 1, MM_READWRITE, 0);
|
MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, PointerPte + 1, MM_READWRITE, 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Acquire the PFN DB lock
|
// Acquire the PFN DB lock
|
||||||
//
|
//
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop each stack page
|
// Loop each stack page
|
||||||
//
|
//
|
||||||
|
@ -362,7 +361,7 @@ MmCreateKernelStack(IN BOOLEAN GuiStack,
|
||||||
// Next PTE
|
// Next PTE
|
||||||
//
|
//
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
|
|
||||||
/* Get a page and write the current invalid PTE */
|
/* Get a page and write the current invalid PTE */
|
||||||
MI_SET_USAGE(MI_USAGE_KERNEL_STACK);
|
MI_SET_USAGE(MI_USAGE_KERNEL_STACK);
|
||||||
MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
|
MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
|
||||||
|
@ -371,7 +370,7 @@ MmCreateKernelStack(IN BOOLEAN GuiStack,
|
||||||
|
|
||||||
/* Initialize the PFN entry for this page */
|
/* Initialize the PFN entry for this page */
|
||||||
MiInitializePfn(PageFrameIndex, PointerPte, 1);
|
MiInitializePfn(PageFrameIndex, PointerPte, 1);
|
||||||
|
|
||||||
/* Write the valid PTE */
|
/* Write the valid PTE */
|
||||||
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
||||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
@ -381,7 +380,7 @@ MmCreateKernelStack(IN BOOLEAN GuiStack,
|
||||||
// Release the PFN lock
|
// Release the PFN lock
|
||||||
//
|
//
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return the stack address
|
// Return the stack address
|
||||||
//
|
//
|
||||||
|
@ -398,25 +397,25 @@ MmGrowKernelStackEx(IN PVOID StackPointer,
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
MMPTE TempPte, InvalidPte;
|
MMPTE TempPte, InvalidPte;
|
||||||
PFN_NUMBER PageFrameIndex;
|
PFN_NUMBER PageFrameIndex;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make sure the stack did not overflow
|
// Make sure the stack did not overflow
|
||||||
//
|
//
|
||||||
ASSERT(((ULONG_PTR)Thread->StackBase - (ULONG_PTR)Thread->StackLimit) <=
|
ASSERT(((ULONG_PTR)Thread->StackBase - (ULONG_PTR)Thread->StackLimit) <=
|
||||||
(KERNEL_LARGE_STACK_SIZE + PAGE_SIZE));
|
(KERNEL_LARGE_STACK_SIZE + PAGE_SIZE));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the current stack limit
|
// Get the current stack limit
|
||||||
//
|
//
|
||||||
LimitPte = MiAddressToPte(Thread->StackLimit);
|
LimitPte = MiAddressToPte(Thread->StackLimit);
|
||||||
ASSERT(LimitPte->u.Hard.Valid == 1);
|
ASSERT(LimitPte->u.Hard.Valid == 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the new one and make sure this isn't a retarded request
|
// Get the new one and make sure this isn't a retarded request
|
||||||
//
|
//
|
||||||
NewLimitPte = MiAddressToPte((PVOID)((ULONG_PTR)StackPointer - GrowSize));
|
NewLimitPte = MiAddressToPte((PVOID)((ULONG_PTR)StackPointer - GrowSize));
|
||||||
if (NewLimitPte == LimitPte) return STATUS_SUCCESS;
|
if (NewLimitPte == LimitPte) return STATUS_SUCCESS;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now make sure you're not going past the reserved space
|
// Now make sure you're not going past the reserved space
|
||||||
//
|
//
|
||||||
|
@ -430,15 +429,15 @@ MmGrowKernelStackEx(IN PVOID StackPointer,
|
||||||
DPRINT1("Thread wants too much stack\n");
|
DPRINT1("Thread wants too much stack\n");
|
||||||
return STATUS_STACK_OVERFLOW;
|
return STATUS_STACK_OVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Calculate the number of new pages
|
// Calculate the number of new pages
|
||||||
//
|
//
|
||||||
LimitPte--;
|
LimitPte--;
|
||||||
|
|
||||||
/* Setup the temporary invalid PTE */
|
/* Setup the temporary invalid PTE */
|
||||||
MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS);
|
MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Acquire the PFN DB lock
|
// Acquire the PFN DB lock
|
||||||
//
|
//
|
||||||
|
@ -457,19 +456,19 @@ MmGrowKernelStackEx(IN PVOID StackPointer,
|
||||||
|
|
||||||
/* Initialize the PFN entry for this page */
|
/* Initialize the PFN entry for this page */
|
||||||
MiInitializePfn(PageFrameIndex, LimitPte, 1);
|
MiInitializePfn(PageFrameIndex, LimitPte, 1);
|
||||||
|
|
||||||
/* Setup the template stack PTE */
|
/* Setup the template stack PTE */
|
||||||
MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, LimitPte, MM_READWRITE, PageFrameIndex);
|
MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, LimitPte, MM_READWRITE, PageFrameIndex);
|
||||||
|
|
||||||
/* Write the valid PTE */
|
/* Write the valid PTE */
|
||||||
MI_WRITE_VALID_PTE(LimitPte--, TempPte);
|
MI_WRITE_VALID_PTE(LimitPte--, TempPte);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the PFN lock
|
// Release the PFN lock
|
||||||
//
|
//
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set the new limit
|
// Set the new limit
|
||||||
//
|
//
|
||||||
|
@ -493,7 +492,7 @@ MmSetMemoryPriorityProcess(IN PEPROCESS Process,
|
||||||
IN UCHAR MemoryPriority)
|
IN UCHAR MemoryPriority)
|
||||||
{
|
{
|
||||||
UCHAR OldPriority;
|
UCHAR OldPriority;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we have less then 16MB of Physical Memory
|
// Check if we have less then 16MB of Physical Memory
|
||||||
//
|
//
|
||||||
|
@ -505,13 +504,13 @@ MmSetMemoryPriorityProcess(IN PEPROCESS Process,
|
||||||
//
|
//
|
||||||
MemoryPriority = MEMORY_PRIORITY_BACKGROUND;
|
MemoryPriority = MEMORY_PRIORITY_BACKGROUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Save the old priority and update it
|
// Save the old priority and update it
|
||||||
//
|
//
|
||||||
OldPriority = (UCHAR)Process->Vm.Flags.MemoryPriority;
|
OldPriority = (UCHAR)Process->Vm.Flags.MemoryPriority;
|
||||||
Process->Vm.Flags.MemoryPriority = MemoryPriority;
|
Process->Vm.Flags.MemoryPriority = MemoryPriority;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return the old priority
|
// Return the old priority
|
||||||
//
|
//
|
||||||
|
@ -524,12 +523,12 @@ MmGetSessionLocaleId(VOID)
|
||||||
{
|
{
|
||||||
PEPROCESS Process;
|
PEPROCESS Process;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the current process
|
// Get the current process
|
||||||
//
|
//
|
||||||
Process = PsGetCurrentProcess();
|
Process = PsGetCurrentProcess();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if it's the Session Leader
|
// Check if it's the Session Leader
|
||||||
//
|
//
|
||||||
|
@ -548,7 +547,7 @@ MmGetSessionLocaleId(VOID)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Not a session leader, return the default
|
// Not a session leader, return the default
|
||||||
//
|
//
|
||||||
|
@ -572,12 +571,12 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
KAFFINITY ProcessAffinityMask = 0;
|
KAFFINITY ProcessAffinityMask = 0;
|
||||||
SectionOffset.QuadPart = (ULONGLONG)0;
|
SectionOffset.QuadPart = (ULONGLONG)0;
|
||||||
*BasePeb = NULL;
|
*BasePeb = NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Attach to Process
|
// Attach to Process
|
||||||
//
|
//
|
||||||
KeAttachProcess(&Process->Pcb);
|
KeAttachProcess(&Process->Pcb);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate the PEB
|
// Allocate the PEB
|
||||||
//
|
//
|
||||||
|
@ -598,7 +597,7 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
MEM_TOP_DOWN,
|
MEM_TOP_DOWN,
|
||||||
PAGE_READONLY);
|
PAGE_READONLY);
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Use SEH in case we can't load the PEB
|
// Use SEH in case we can't load the PEB
|
||||||
//
|
//
|
||||||
|
@ -608,7 +607,7 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
// Initialize the PEB
|
// Initialize the PEB
|
||||||
//
|
//
|
||||||
RtlZeroMemory(Peb, sizeof(PEB));
|
RtlZeroMemory(Peb, sizeof(PEB));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set up data
|
// Set up data
|
||||||
//
|
//
|
||||||
|
@ -616,14 +615,14 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
Peb->InheritedAddressSpace = InitialPeb->InheritedAddressSpace;
|
Peb->InheritedAddressSpace = InitialPeb->InheritedAddressSpace;
|
||||||
Peb->Mutant = InitialPeb->Mutant;
|
Peb->Mutant = InitialPeb->Mutant;
|
||||||
Peb->ImageUsesLargePages = InitialPeb->ImageUsesLargePages;
|
Peb->ImageUsesLargePages = InitialPeb->ImageUsesLargePages;
|
||||||
|
|
||||||
//
|
//
|
||||||
// NLS
|
// NLS
|
||||||
//
|
//
|
||||||
Peb->AnsiCodePageData = (PCHAR)TableBase + ExpAnsiCodePageDataOffset;
|
Peb->AnsiCodePageData = (PCHAR)TableBase + ExpAnsiCodePageDataOffset;
|
||||||
Peb->OemCodePageData = (PCHAR)TableBase + ExpOemCodePageDataOffset;
|
Peb->OemCodePageData = (PCHAR)TableBase + ExpOemCodePageDataOffset;
|
||||||
Peb->UnicodeCaseTableData = (PCHAR)TableBase + ExpUnicodeCaseTableDataOffset;
|
Peb->UnicodeCaseTableData = (PCHAR)TableBase + ExpUnicodeCaseTableDataOffset;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Default Version Data (could get changed below)
|
// Default Version Data (could get changed below)
|
||||||
//
|
//
|
||||||
|
@ -632,7 +631,7 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
Peb->OSBuildNumber = (USHORT)(NtBuildNumber & 0x3FFF);
|
Peb->OSBuildNumber = (USHORT)(NtBuildNumber & 0x3FFF);
|
||||||
Peb->OSPlatformId = 2; /* VER_PLATFORM_WIN32_NT */
|
Peb->OSPlatformId = 2; /* VER_PLATFORM_WIN32_NT */
|
||||||
Peb->OSCSDVersion = (USHORT)CmNtCSDVersion;
|
Peb->OSCSDVersion = (USHORT)CmNtCSDVersion;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Heap and Debug Data
|
// Heap and Debug Data
|
||||||
//
|
//
|
||||||
|
@ -648,7 +647,7 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
*/
|
*/
|
||||||
Peb->MaximumNumberOfHeaps = (PAGE_SIZE - sizeof(PEB)) / sizeof(PVOID);
|
Peb->MaximumNumberOfHeaps = (PAGE_SIZE - sizeof(PEB)) / sizeof(PVOID);
|
||||||
Peb->ProcessHeaps = (PVOID*)(Peb + 1);
|
Peb->ProcessHeaps = (PVOID*)(Peb + 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Session ID
|
// Session ID
|
||||||
//
|
//
|
||||||
|
@ -663,7 +662,7 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Use SEH in case we can't load the image
|
// Use SEH in case we can't load the image
|
||||||
//
|
//
|
||||||
|
@ -684,7 +683,7 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
_SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT);
|
_SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT);
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse the headers
|
// Parse the headers
|
||||||
//
|
//
|
||||||
|
@ -711,7 +710,7 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
sizeof(IMAGE_LOAD_CONFIG_DIRECTORY),
|
sizeof(IMAGE_LOAD_CONFIG_DIRECTORY),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Write subsystem data
|
// Write subsystem data
|
||||||
//
|
//
|
||||||
|
@ -732,7 +731,7 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
Peb->OSBuildNumber = (NtHeaders->OptionalHeader.Win32VersionValue >> 16) & 0x3FFF;
|
Peb->OSBuildNumber = (NtHeaders->OptionalHeader.Win32VersionValue >> 16) & 0x3FFF;
|
||||||
Peb->OSPlatformId = (NtHeaders->OptionalHeader.Win32VersionValue >> 30) ^ 2;
|
Peb->OSPlatformId = (NtHeaders->OptionalHeader.Win32VersionValue >> 30) ^ 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Process the image config data overrides if specfied
|
// Process the image config data overrides if specfied
|
||||||
//
|
//
|
||||||
|
@ -748,7 +747,7 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
//
|
//
|
||||||
Peb->OSCSDVersion = ImageConfigData->CSDVersion;
|
Peb->OSCSDVersion = ImageConfigData->CSDVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Process affinity mask ovverride
|
// Process affinity mask ovverride
|
||||||
//
|
//
|
||||||
|
@ -760,7 +759,7 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
ProcessAffinityMask = ImageConfigData->ProcessAffinityMask;
|
ProcessAffinityMask = ImageConfigData->ProcessAffinityMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is a UP image
|
// Check if this is a UP image
|
||||||
if (Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY)
|
if (Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY)
|
||||||
|
@ -788,7 +787,7 @@ MmCreatePeb(IN PEPROCESS Process,
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Detach from the Process
|
// Detach from the Process
|
||||||
//
|
//
|
||||||
|
@ -807,18 +806,18 @@ MmCreateTeb(IN PEPROCESS Process,
|
||||||
PTEB Teb;
|
PTEB Teb;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
*BaseTeb = NULL;
|
*BaseTeb = NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Attach to Target
|
// Attach to Target
|
||||||
//
|
//
|
||||||
KeAttachProcess(&Process->Pcb);
|
KeAttachProcess(&Process->Pcb);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate the TEB
|
// Allocate the TEB
|
||||||
//
|
//
|
||||||
Status = MiCreatePebOrTeb(Process, sizeof(TEB), (PULONG_PTR)&Teb);
|
Status = MiCreatePebOrTeb(Process, sizeof(TEB), (PULONG_PTR)&Teb);
|
||||||
ASSERT(NT_SUCCESS(Status));
|
ASSERT(NT_SUCCESS(Status));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Use SEH in case we can't load the TEB
|
// Use SEH in case we can't load the TEB
|
||||||
//
|
//
|
||||||
|
@ -828,18 +827,18 @@ MmCreateTeb(IN PEPROCESS Process,
|
||||||
// Initialize the PEB
|
// Initialize the PEB
|
||||||
//
|
//
|
||||||
RtlZeroMemory(Teb, sizeof(TEB));
|
RtlZeroMemory(Teb, sizeof(TEB));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set TIB Data
|
// Set TIB Data
|
||||||
//
|
//
|
||||||
Teb->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
|
Teb->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
|
||||||
Teb->NtTib.Self = (PNT_TIB)Teb;
|
Teb->NtTib.Self = (PNT_TIB)Teb;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Identify this as an OS/2 V3.0 ("Cruiser") TIB
|
// Identify this as an OS/2 V3.0 ("Cruiser") TIB
|
||||||
//
|
//
|
||||||
Teb->NtTib.Version = 30 << 8;
|
Teb->NtTib.Version = 30 << 8;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set TEB Data
|
// Set TEB Data
|
||||||
//
|
//
|
||||||
|
@ -847,7 +846,7 @@ MmCreateTeb(IN PEPROCESS Process,
|
||||||
Teb->RealClientId = *ClientId;
|
Teb->RealClientId = *ClientId;
|
||||||
Teb->ProcessEnvironmentBlock = Process->Peb;
|
Teb->ProcessEnvironmentBlock = Process->Peb;
|
||||||
Teb->CurrentLocale = PsDefaultThreadLocaleId;
|
Teb->CurrentLocale = PsDefaultThreadLocaleId;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we have a grandparent TEB
|
// Check if we have a grandparent TEB
|
||||||
//
|
//
|
||||||
|
@ -912,7 +911,7 @@ MiInitializeWorkingSetList(IN PEPROCESS CurrentProcess)
|
||||||
MmWorkingSetList->FirstDynamic = 2;
|
MmWorkingSetList->FirstDynamic = 2;
|
||||||
MmWorkingSetList->NextSlot = 3;
|
MmWorkingSetList->NextSlot = 3;
|
||||||
MmWorkingSetList->LastInitializedWsle = 4;
|
MmWorkingSetList->LastInitializedWsle = 4;
|
||||||
|
|
||||||
/* The rule is that the owner process is always in the FLINK of the PDE's PFN entry */
|
/* The rule is that the owner process is always in the FLINK of the PDE's PFN entry */
|
||||||
Pfn1 = MiGetPfnEntry(MiAddressToPte(PDE_BASE)->u.Hard.PageFrameNumber);
|
Pfn1 = MiGetPfnEntry(MiAddressToPte(PDE_BASE)->u.Hard.PageFrameNumber);
|
||||||
ASSERT(Pfn1->u4.PteFrame == MiGetPfnEntryIndex(Pfn1));
|
ASSERT(Pfn1->u4.PteFrame == MiGetPfnEntryIndex(Pfn1));
|
||||||
|
@ -940,14 +939,14 @@ MmInitializeProcessAddressSpace(IN PEPROCESS Process,
|
||||||
PCHAR Destination;
|
PCHAR Destination;
|
||||||
USHORT Length = 0;
|
USHORT Length = 0;
|
||||||
MMPTE TempPte;
|
MMPTE TempPte;
|
||||||
|
|
||||||
/* We should have a PDE */
|
/* We should have a PDE */
|
||||||
ASSERT(Process->Pcb.DirectoryTableBase[0] != 0);
|
ASSERT(Process->Pcb.DirectoryTableBase[0] != 0);
|
||||||
ASSERT(Process->PdeUpdateNeeded == FALSE);
|
ASSERT(Process->PdeUpdateNeeded == FALSE);
|
||||||
|
|
||||||
/* Attach to the process */
|
/* Attach to the process */
|
||||||
KeAttachProcess(&Process->Pcb);
|
KeAttachProcess(&Process->Pcb);
|
||||||
|
|
||||||
/* The address space should now been in phase 1 or 0 */
|
/* The address space should now been in phase 1 or 0 */
|
||||||
ASSERT(Process->AddressSpaceInitialized <= 1);
|
ASSERT(Process->AddressSpaceInitialized <= 1);
|
||||||
Process->AddressSpaceInitialized = 2;
|
Process->AddressSpaceInitialized = 2;
|
||||||
|
@ -972,7 +971,7 @@ MmInitializeProcessAddressSpace(IN PEPROCESS Process,
|
||||||
PointerPde = MiAddressToPde(HYPER_SPACE);
|
PointerPde = MiAddressToPde(HYPER_SPACE);
|
||||||
PageFrameNumber = PFN_FROM_PTE(PointerPde);
|
PageFrameNumber = PFN_FROM_PTE(PointerPde);
|
||||||
MiInitializePfn(PageFrameNumber, (PMMPTE)PointerPde, TRUE);
|
MiInitializePfn(PageFrameNumber, (PMMPTE)PointerPde, TRUE);
|
||||||
|
|
||||||
/* Setup the PFN for the PTE for the working set */
|
/* Setup the PFN for the PTE for the working set */
|
||||||
PointerPte = MiAddressToPte(MI_WORKING_SET_LIST);
|
PointerPte = MiAddressToPte(MI_WORKING_SET_LIST);
|
||||||
MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, MM_READWRITE, 0);
|
MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, MM_READWRITE, 0);
|
||||||
|
@ -1057,7 +1056,7 @@ MmInitializeProcessAddressSpace(IN PEPROCESS Process,
|
||||||
/* Save the pointer */
|
/* Save the pointer */
|
||||||
Process->SectionBaseAddress = ImageBase;
|
Process->SectionBaseAddress = ImageBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Be nice and detach */
|
/* Be nice and detach */
|
||||||
KeDetachProcess();
|
KeDetachProcess();
|
||||||
|
|
||||||
|
@ -1092,7 +1091,7 @@ NTAPI
|
||||||
INIT_FUNCTION
|
INIT_FUNCTION
|
||||||
MmInitializeHandBuiltProcess2(IN PEPROCESS Process)
|
MmInitializeHandBuiltProcess2(IN PEPROCESS Process)
|
||||||
{
|
{
|
||||||
/* Lock the VAD, ARM3-owned ranges away */
|
/* Lock the VAD, ARM3-owned ranges away */
|
||||||
MiRosTakeOverPebTebRanges(Process);
|
MiRosTakeOverPebTebRanges(Process);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1116,13 +1115,13 @@ MmCreateProcessAddressSpace(IN ULONG MinWs,
|
||||||
|
|
||||||
/* Choose a process color */
|
/* Choose a process color */
|
||||||
Process->NextPageColor = RtlRandom(&MmProcessColorSeed);
|
Process->NextPageColor = RtlRandom(&MmProcessColorSeed);
|
||||||
|
|
||||||
/* Setup the hyperspace lock */
|
/* Setup the hyperspace lock */
|
||||||
KeInitializeSpinLock(&Process->HyperSpaceLock);
|
KeInitializeSpinLock(&Process->HyperSpaceLock);
|
||||||
|
|
||||||
/* Lock PFN database */
|
/* Lock PFN database */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
/* Get a zero page for the PDE, if possible */
|
/* Get a zero page for the PDE, if possible */
|
||||||
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
|
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
|
||||||
MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY);
|
MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY);
|
||||||
|
@ -1131,13 +1130,13 @@ MmCreateProcessAddressSpace(IN ULONG MinWs,
|
||||||
{
|
{
|
||||||
/* No zero pages, grab a free one */
|
/* No zero pages, grab a free one */
|
||||||
PdeIndex = MiRemoveAnyPage(Color);
|
PdeIndex = MiRemoveAnyPage(Color);
|
||||||
|
|
||||||
/* Zero it outside the PFN lock */
|
/* Zero it outside the PFN lock */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
MiZeroPhysicalPage(PdeIndex);
|
MiZeroPhysicalPage(PdeIndex);
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a zero page for hyperspace, if possible */
|
/* Get a zero page for hyperspace, if possible */
|
||||||
MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY);
|
MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY);
|
||||||
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
|
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
|
||||||
|
@ -1146,7 +1145,7 @@ MmCreateProcessAddressSpace(IN ULONG MinWs,
|
||||||
{
|
{
|
||||||
/* No zero pages, grab a free one */
|
/* No zero pages, grab a free one */
|
||||||
HyperIndex = MiRemoveAnyPage(Color);
|
HyperIndex = MiRemoveAnyPage(Color);
|
||||||
|
|
||||||
/* Zero it outside the PFN lock */
|
/* Zero it outside the PFN lock */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
MiZeroPhysicalPage(HyperIndex);
|
MiZeroPhysicalPage(HyperIndex);
|
||||||
|
@ -1161,7 +1160,7 @@ MmCreateProcessAddressSpace(IN ULONG MinWs,
|
||||||
{
|
{
|
||||||
/* No zero pages, grab a free one */
|
/* No zero pages, grab a free one */
|
||||||
WsListIndex = MiRemoveAnyPage(Color);
|
WsListIndex = MiRemoveAnyPage(Color);
|
||||||
|
|
||||||
/* Zero it outside the PFN lock */
|
/* Zero it outside the PFN lock */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
MiZeroPhysicalPage(WsListIndex);
|
MiZeroPhysicalPage(WsListIndex);
|
||||||
|
@ -1183,7 +1182,7 @@ MmCreateProcessAddressSpace(IN ULONG MinWs,
|
||||||
|
|
||||||
/* Make sure we don't already have a page directory setup */
|
/* Make sure we don't already have a page directory setup */
|
||||||
ASSERT(Process->Pcb.DirectoryTableBase[0] == 0);
|
ASSERT(Process->Pcb.DirectoryTableBase[0] == 0);
|
||||||
|
|
||||||
/* Get a PTE to map hyperspace */
|
/* Get a PTE to map hyperspace */
|
||||||
PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
|
PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
|
||||||
ASSERT(PointerPte != NULL);
|
ASSERT(PointerPte != NULL);
|
||||||
|
@ -1268,16 +1267,16 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
|
||||||
PMMVAD Vad;
|
PMMVAD Vad;
|
||||||
PMM_AVL_TABLE VadTree;
|
PMM_AVL_TABLE VadTree;
|
||||||
PETHREAD Thread = PsGetCurrentThread();
|
PETHREAD Thread = PsGetCurrentThread();
|
||||||
|
|
||||||
/* Only support this */
|
/* Only support this */
|
||||||
ASSERT(Process->AddressSpaceInitialized == 2);
|
ASSERT(Process->AddressSpaceInitialized == 2);
|
||||||
|
|
||||||
/* Lock the process address space from changes */
|
/* Lock the process address space from changes */
|
||||||
MmLockAddressSpace(&Process->Vm);
|
MmLockAddressSpace(&Process->Vm);
|
||||||
|
|
||||||
/* VM is deleted now */
|
/* VM is deleted now */
|
||||||
Process->VmDeleted = TRUE;
|
Process->VmDeleted = TRUE;
|
||||||
|
|
||||||
/* Enumerate the VADs */
|
/* Enumerate the VADs */
|
||||||
VadTree = &Process->VadRoot;
|
VadTree = &Process->VadRoot;
|
||||||
while (VadTree->NumberGenericTableElements)
|
while (VadTree->NumberGenericTableElements)
|
||||||
|
@ -1294,7 +1293,7 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
|
||||||
|
|
||||||
/* Only regular VADs supported for now */
|
/* Only regular VADs supported for now */
|
||||||
ASSERT(Vad->u.VadFlags.VadType == VadNone);
|
ASSERT(Vad->u.VadFlags.VadType == VadNone);
|
||||||
|
|
||||||
/* Check if this is a section VAD */
|
/* Check if this is a section VAD */
|
||||||
if (!(Vad->u.VadFlags.PrivateMemory) && (Vad->ControlArea))
|
if (!(Vad->u.VadFlags.PrivateMemory) && (Vad->ControlArea))
|
||||||
{
|
{
|
||||||
|
@ -1307,11 +1306,11 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
|
||||||
MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
|
MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
|
||||||
(Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
|
(Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
|
||||||
Vad);
|
Vad);
|
||||||
|
|
||||||
/* Release the working set */
|
/* Release the working set */
|
||||||
MiUnlockProcessWorkingSet(Process, Thread);
|
MiUnlockProcessWorkingSet(Process, Thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip ARM3 fake VADs, they'll be freed by MmDeleteProcessAddresSpace */
|
/* Skip ARM3 fake VADs, they'll be freed by MmDeleteProcessAddresSpace */
|
||||||
if (Vad->u.VadFlags.Spare == 1)
|
if (Vad->u.VadFlags.Spare == 1)
|
||||||
{
|
{
|
||||||
|
@ -1319,11 +1318,11 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
|
||||||
Vad->u.VadFlags.Spare = 2;
|
Vad->u.VadFlags.Spare = 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the VAD memory */
|
/* Free the VAD memory */
|
||||||
ExFreePool(Vad);
|
ExFreePool(Vad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the address space */
|
/* Release the address space */
|
||||||
MmUnlockAddressSpace(&Process->Vm);
|
MmUnlockAddressSpace(&Process->Vm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::SECTION"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -82,14 +81,14 @@ MiMakeProtectionMask(IN ULONG Protect)
|
||||||
|
|
||||||
/* PAGE_EXECUTE_WRITECOMBINE is theoretically the maximum */
|
/* PAGE_EXECUTE_WRITECOMBINE is theoretically the maximum */
|
||||||
if (Protect >= (PAGE_WRITECOMBINE * 2)) return MM_INVALID_PROTECTION;
|
if (Protect >= (PAGE_WRITECOMBINE * 2)) return MM_INVALID_PROTECTION;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Windows API protection mask can be understood as two bitfields, differing
|
* Windows API protection mask can be understood as two bitfields, differing
|
||||||
* by whether or not execute rights are being requested
|
* by whether or not execute rights are being requested
|
||||||
*/
|
*/
|
||||||
Mask1 = Protect & 0xF;
|
Mask1 = Protect & 0xF;
|
||||||
Mask2 = (Protect >> 4) & 0xF;
|
Mask2 = (Protect >> 4) & 0xF;
|
||||||
|
|
||||||
/* Check which field is there */
|
/* Check which field is there */
|
||||||
if (!Mask1)
|
if (!Mask1)
|
||||||
{
|
{
|
||||||
|
@ -103,10 +102,10 @@ MiMakeProtectionMask(IN ULONG Protect)
|
||||||
if (Mask2) return MM_INVALID_PROTECTION;
|
if (Mask2) return MM_INVALID_PROTECTION;
|
||||||
ProtectMask = MmUserProtectionToMask1[Mask1];
|
ProtectMask = MmUserProtectionToMask1[Mask1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the final mask is a valid one */
|
/* Make sure the final mask is a valid one */
|
||||||
if (ProtectMask == MM_INVALID_PROTECTION) return MM_INVALID_PROTECTION;
|
if (ProtectMask == MM_INVALID_PROTECTION) return MM_INVALID_PROTECTION;
|
||||||
|
|
||||||
/* Check for PAGE_GUARD option */
|
/* Check for PAGE_GUARD option */
|
||||||
if (Protect & PAGE_GUARD)
|
if (Protect & PAGE_GUARD)
|
||||||
{
|
{
|
||||||
|
@ -117,41 +116,41 @@ MiMakeProtectionMask(IN ULONG Protect)
|
||||||
/* Fail such requests */
|
/* Fail such requests */
|
||||||
return MM_INVALID_PROTECTION;
|
return MM_INVALID_PROTECTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This actually turns on guard page in this scenario! */
|
/* This actually turns on guard page in this scenario! */
|
||||||
ProtectMask |= MM_DECOMMIT;
|
ProtectMask |= MM_DECOMMIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for nocache option */
|
/* Check for nocache option */
|
||||||
if (Protect & PAGE_NOCACHE)
|
if (Protect & PAGE_NOCACHE)
|
||||||
{
|
{
|
||||||
/* The earlier check should've eliminated this possibility */
|
/* The earlier check should've eliminated this possibility */
|
||||||
ASSERT((Protect & PAGE_GUARD) == 0);
|
ASSERT((Protect & PAGE_GUARD) == 0);
|
||||||
|
|
||||||
/* Check for no-access page or write combine page */
|
/* Check for no-access page or write combine page */
|
||||||
if ((ProtectMask == MM_NOACCESS) || (Protect & PAGE_WRITECOMBINE))
|
if ((ProtectMask == MM_NOACCESS) || (Protect & PAGE_WRITECOMBINE))
|
||||||
{
|
{
|
||||||
/* Such a request is invalid */
|
/* Such a request is invalid */
|
||||||
return MM_INVALID_PROTECTION;
|
return MM_INVALID_PROTECTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the PTE flag */
|
/* Add the PTE flag */
|
||||||
ProtectMask |= MM_NOCACHE;
|
ProtectMask |= MM_NOCACHE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for write combine option */
|
/* Check for write combine option */
|
||||||
if (Protect & PAGE_WRITECOMBINE)
|
if (Protect & PAGE_WRITECOMBINE)
|
||||||
{
|
{
|
||||||
/* The two earlier scenarios should've caught this */
|
/* The two earlier scenarios should've caught this */
|
||||||
ASSERT((Protect & (PAGE_GUARD | PAGE_NOACCESS)) == 0);
|
ASSERT((Protect & (PAGE_GUARD | PAGE_NOACCESS)) == 0);
|
||||||
|
|
||||||
/* Don't allow on no-access pages */
|
/* Don't allow on no-access pages */
|
||||||
if (ProtectMask == MM_NOACCESS) return MM_INVALID_PROTECTION;
|
if (ProtectMask == MM_NOACCESS) return MM_INVALID_PROTECTION;
|
||||||
|
|
||||||
/* This actually turns on write-combine in this scenario! */
|
/* This actually turns on write-combine in this scenario! */
|
||||||
ProtectMask |= MM_NOACCESS;
|
ProtectMask |= MM_NOACCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the final MM PTE protection mask */
|
/* Return the final MM PTE protection mask */
|
||||||
return ProtectMask;
|
return ProtectMask;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +169,7 @@ MiInitializeSystemSpaceMap(IN PVOID InputSession OPTIONAL)
|
||||||
/* Initialize the system space lock */
|
/* Initialize the system space lock */
|
||||||
Session->SystemSpaceViewLockPointer = &Session->SystemSpaceViewLock;
|
Session->SystemSpaceViewLockPointer = &Session->SystemSpaceViewLock;
|
||||||
KeInitializeGuardedMutex(Session->SystemSpaceViewLockPointer);
|
KeInitializeGuardedMutex(Session->SystemSpaceViewLockPointer);
|
||||||
|
|
||||||
/* Set the start address */
|
/* Set the start address */
|
||||||
Session->SystemSpaceViewStart = MiSystemViewStart;
|
Session->SystemSpaceViewStart = MiSystemViewStart;
|
||||||
|
|
||||||
|
@ -202,7 +201,7 @@ MiInitializeSystemSpaceMap(IN PVOID InputSession OPTIONAL)
|
||||||
' mM');
|
' mM');
|
||||||
ASSERT(Session->SystemSpaceViewTable != NULL);
|
ASSERT(Session->SystemSpaceViewTable != NULL);
|
||||||
RtlZeroMemory(Session->SystemSpaceViewTable, AllocSize);
|
RtlZeroMemory(Session->SystemSpaceViewTable, AllocSize);
|
||||||
|
|
||||||
/* Success */
|
/* Success */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -263,7 +262,7 @@ MiAddMappedPtes(IN PMMPTE FirstPte,
|
||||||
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
|
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
|
||||||
ASSERT(ControlArea->u.Flags.Rom == 0);
|
ASSERT(ControlArea->u.Flags.Rom == 0);
|
||||||
ASSERT(ControlArea->FilePointer == NULL);
|
ASSERT(ControlArea->FilePointer == NULL);
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
ASSERT(PteCount != 0);
|
ASSERT(PteCount != 0);
|
||||||
ASSERT(ControlArea->NumberOfMappedViews >= 1);
|
ASSERT(ControlArea->NumberOfMappedViews >= 1);
|
||||||
|
@ -292,10 +291,10 @@ MiAddMappedPtes(IN PMMPTE FirstPte,
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
while (TRUE);
|
while (TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The PTE should be completely clear */
|
/* The PTE should be completely clear */
|
||||||
ASSERT(PointerPte->u.Long == 0);
|
ASSERT(PointerPte->u.Long == 0);
|
||||||
|
|
||||||
/* Build the prototype PTE and write it */
|
/* Build the prototype PTE and write it */
|
||||||
MI_MAKE_PROTOTYPE_PTE(&TempPte, ProtoPte);
|
MI_MAKE_PROTOTYPE_PTE(&TempPte, ProtoPte);
|
||||||
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
||||||
|
@ -327,7 +326,7 @@ MiFillSystemPageDirectory(IN PVOID Base,
|
||||||
|
|
||||||
/* Find the system double-mapped PDE that describes this mapping */
|
/* Find the system double-mapped PDE that describes this mapping */
|
||||||
SystemMapPde = &MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)];
|
SystemMapPde = &MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)];
|
||||||
|
|
||||||
/* Use the PDE template and loop the PDEs */
|
/* Use the PDE template and loop the PDEs */
|
||||||
TempPde = ValidKernelPde;
|
TempPde = ValidKernelPde;
|
||||||
while (PointerPde <= LastPde)
|
while (PointerPde <= LastPde)
|
||||||
|
@ -352,7 +351,7 @@ MiFillSystemPageDirectory(IN PVOID Base,
|
||||||
|
|
||||||
/* Make the system PDE entry valid */
|
/* Make the system PDE entry valid */
|
||||||
MI_WRITE_VALID_PDE(SystemMapPde, TempPde);
|
MI_WRITE_VALID_PDE(SystemMapPde, TempPde);
|
||||||
|
|
||||||
/* The system PDE entry might be the PDE itself, so check for this */
|
/* The system PDE entry might be the PDE itself, so check for this */
|
||||||
if (PointerPde->u.Hard.Valid == 0)
|
if (PointerPde->u.Hard.Valid == 0)
|
||||||
{
|
{
|
||||||
|
@ -375,10 +374,10 @@ MiCheckPurgeAndUpMapCount(IN PCONTROL_AREA ControlArea,
|
||||||
IN BOOLEAN FailIfSystemViews)
|
IN BOOLEAN FailIfSystemViews)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
|
||||||
/* Flag not yet supported */
|
/* Flag not yet supported */
|
||||||
ASSERT(FailIfSystemViews == FALSE);
|
ASSERT(FailIfSystemViews == FALSE);
|
||||||
|
|
||||||
/* Lock the PFN database */
|
/* Lock the PFN database */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
|
@ -412,12 +411,12 @@ MiLocateSubsection(IN PMMVAD Vad,
|
||||||
|
|
||||||
/* Get the subsection */
|
/* Get the subsection */
|
||||||
Subsection = (PSUBSECTION)(ControlArea + 1);
|
Subsection = (PSUBSECTION)(ControlArea + 1);
|
||||||
|
|
||||||
/* We only support single-subsection segments */
|
/* We only support single-subsection segments */
|
||||||
ASSERT(Subsection->SubsectionBase != NULL);
|
ASSERT(Subsection->SubsectionBase != NULL);
|
||||||
ASSERT(Vad->FirstPrototypePte >= Subsection->SubsectionBase);
|
ASSERT(Vad->FirstPrototypePte >= Subsection->SubsectionBase);
|
||||||
ASSERT(Vad->FirstPrototypePte < &Subsection->SubsectionBase[Subsection->PtesInSubsection]);
|
ASSERT(Vad->FirstPrototypePte < &Subsection->SubsectionBase[Subsection->PtesInSubsection]);
|
||||||
|
|
||||||
/* Compute the PTE offset */
|
/* Compute the PTE offset */
|
||||||
PteOffset = (ULONG_PTR)Vpn - Vad->StartingVpn;
|
PteOffset = (ULONG_PTR)Vpn - Vad->StartingVpn;
|
||||||
PteOffset += Vad->FirstPrototypePte - Subsection->SubsectionBase;
|
PteOffset += Vad->FirstPrototypePte - Subsection->SubsectionBase;
|
||||||
|
@ -425,7 +424,7 @@ MiLocateSubsection(IN PMMVAD Vad,
|
||||||
/* Again, we only support single-subsection segments */
|
/* Again, we only support single-subsection segments */
|
||||||
ASSERT(PteOffset < 0xF0000000);
|
ASSERT(PteOffset < 0xF0000000);
|
||||||
ASSERT(PteOffset < Subsection->PtesInSubsection);
|
ASSERT(PteOffset < Subsection->PtesInSubsection);
|
||||||
|
|
||||||
/* Return the subsection */
|
/* Return the subsection */
|
||||||
return Subsection;
|
return Subsection;
|
||||||
}
|
}
|
||||||
|
@ -448,7 +447,7 @@ MiSegmentDelete(IN PSEGMENT Segment)
|
||||||
/* Make sure control area is on the right delete path */
|
/* Make sure control area is on the right delete path */
|
||||||
ASSERT(ControlArea->u.Flags.BeingDeleted == 1);
|
ASSERT(ControlArea->u.Flags.BeingDeleted == 1);
|
||||||
ASSERT(ControlArea->WritableUserReferences == 0);
|
ASSERT(ControlArea->WritableUserReferences == 0);
|
||||||
|
|
||||||
/* These things are not supported yet */
|
/* These things are not supported yet */
|
||||||
ASSERT(ControlArea->DereferenceList.Flink == NULL);
|
ASSERT(ControlArea->DereferenceList.Flink == NULL);
|
||||||
ASSERT(!(ControlArea->u.Flags.Image) & !(ControlArea->u.Flags.File));
|
ASSERT(!(ControlArea->u.Flags.Image) & !(ControlArea->u.Flags.File));
|
||||||
|
@ -462,7 +461,7 @@ MiSegmentDelete(IN PSEGMENT Segment)
|
||||||
|
|
||||||
/* Lock the PFN database */
|
/* Lock the PFN database */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
/* Check if the master PTE is invalid */
|
/* Check if the master PTE is invalid */
|
||||||
PteForProto = MiAddressToPte(PointerPte);
|
PteForProto = MiAddressToPte(PointerPte);
|
||||||
if (!PteForProto->u.Hard.Valid)
|
if (!PteForProto->u.Hard.Valid)
|
||||||
|
@ -497,7 +496,7 @@ MiSegmentDelete(IN PSEGMENT Segment)
|
||||||
PointerPte->u.Long = 0;
|
PointerPte->u.Long = 0;
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the PFN lock */
|
/* Release the PFN lock */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
|
@ -513,7 +512,7 @@ MiCheckControlArea(IN PCONTROL_AREA ControlArea,
|
||||||
{
|
{
|
||||||
BOOLEAN DeleteSegment = FALSE;
|
BOOLEAN DeleteSegment = FALSE;
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
|
||||||
/* Check if this is the last reference or view */
|
/* Check if this is the last reference or view */
|
||||||
if (!(ControlArea->NumberOfMappedViews) &&
|
if (!(ControlArea->NumberOfMappedViews) &&
|
||||||
!(ControlArea->NumberOfSectionReferences))
|
!(ControlArea->NumberOfSectionReferences))
|
||||||
|
@ -531,7 +530,7 @@ MiCheckControlArea(IN PCONTROL_AREA ControlArea,
|
||||||
|
|
||||||
/* Release the PFN lock */
|
/* Release the PFN lock */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
/* Delete the segment if needed */
|
/* Delete the segment if needed */
|
||||||
if (DeleteSegment)
|
if (DeleteSegment)
|
||||||
{
|
{
|
||||||
|
@ -557,7 +556,7 @@ MiRemoveMappedView(IN PEPROCESS CurrentProcess,
|
||||||
ASSERT(Vad->u2.VadFlags2.ExtendableFile == FALSE);
|
ASSERT(Vad->u2.VadFlags2.ExtendableFile == FALSE);
|
||||||
ASSERT(ControlArea);
|
ASSERT(ControlArea);
|
||||||
ASSERT(ControlArea->FilePointer == NULL);
|
ASSERT(ControlArea->FilePointer == NULL);
|
||||||
|
|
||||||
/* Delete the actual virtual memory pages */
|
/* Delete the actual virtual memory pages */
|
||||||
MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
|
MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
|
||||||
(Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
|
(Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
|
||||||
|
@ -600,17 +599,17 @@ MiMapViewInSystemSpace(IN PVOID Section,
|
||||||
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
|
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
|
||||||
ASSERT(ControlArea->u.Flags.Rom == 0);
|
ASSERT(ControlArea->u.Flags.Rom == 0);
|
||||||
ASSERT(ControlArea->u.Flags.WasPurged == 0);
|
ASSERT(ControlArea->u.Flags.WasPurged == 0);
|
||||||
|
|
||||||
/* Increase the reference and map count on the control area, no purges yet */
|
/* Increase the reference and map count on the control area, no purges yet */
|
||||||
Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
|
Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
|
||||||
ASSERT(NT_SUCCESS(Status));
|
ASSERT(NT_SUCCESS(Status));
|
||||||
|
|
||||||
/* Get the section size at creation time */
|
/* Get the section size at creation time */
|
||||||
SectionSize = ((PSECTION)Section)->SizeOfSection.LowPart;
|
SectionSize = ((PSECTION)Section)->SizeOfSection.LowPart;
|
||||||
|
|
||||||
/* If the caller didn't specify a view size, assume the whole section */
|
/* If the caller didn't specify a view size, assume the whole section */
|
||||||
if (!(*ViewSize)) *ViewSize = SectionSize;
|
if (!(*ViewSize)) *ViewSize = SectionSize;
|
||||||
|
|
||||||
/* Check if the caller wanted a larger section than the view */
|
/* Check if the caller wanted a larger section than the view */
|
||||||
if (*ViewSize > SectionSize)
|
if (*ViewSize > SectionSize)
|
||||||
{
|
{
|
||||||
|
@ -622,7 +621,7 @@ MiMapViewInSystemSpace(IN PVOID Section,
|
||||||
/* Get the number of 64K buckets required for this mapping */
|
/* Get the number of 64K buckets required for this mapping */
|
||||||
Buckets = *ViewSize / MI_SYSTEM_VIEW_BUCKET_SIZE;
|
Buckets = *ViewSize / MI_SYSTEM_VIEW_BUCKET_SIZE;
|
||||||
if (*ViewSize & (MI_SYSTEM_VIEW_BUCKET_SIZE - 1)) Buckets++;
|
if (*ViewSize & (MI_SYSTEM_VIEW_BUCKET_SIZE - 1)) Buckets++;
|
||||||
|
|
||||||
/* Check if the view is more than 4GB large */
|
/* Check if the view is more than 4GB large */
|
||||||
if (Buckets >= MI_SYSTEM_VIEW_BUCKET_SIZE)
|
if (Buckets >= MI_SYSTEM_VIEW_BUCKET_SIZE)
|
||||||
{
|
{
|
||||||
|
@ -645,7 +644,7 @@ MiMapViewInSystemSpace(IN PVOID Section,
|
||||||
BYTES_TO_PAGES(*ViewSize),
|
BYTES_TO_PAGES(*ViewSize),
|
||||||
ControlArea);
|
ControlArea);
|
||||||
ASSERT(NT_SUCCESS(Status));
|
ASSERT(NT_SUCCESS(Status));
|
||||||
|
|
||||||
/* Return the base adress of the mapping and success */
|
/* Return the base adress of the mapping and success */
|
||||||
*MappedBase = Base;
|
*MappedBase = Base;
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
@ -682,10 +681,10 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
||||||
ASSERT(ControlArea->u.Flags.Rom == 0);
|
ASSERT(ControlArea->u.Flags.Rom == 0);
|
||||||
ASSERT(ControlArea->FilePointer == NULL);
|
ASSERT(ControlArea->FilePointer == NULL);
|
||||||
ASSERT(Segment->SegmentFlags.TotalNumberOfPtes4132 == 0);
|
ASSERT(Segment->SegmentFlags.TotalNumberOfPtes4132 == 0);
|
||||||
|
|
||||||
/* Based sections not supported */
|
/* Based sections not supported */
|
||||||
ASSERT(Section->Address.StartingVpn == 0);
|
ASSERT(Section->Address.StartingVpn == 0);
|
||||||
|
|
||||||
/* These flags/parameters are not supported */
|
/* These flags/parameters are not supported */
|
||||||
ASSERT((AllocationType & MEM_DOS_LIM) == 0);
|
ASSERT((AllocationType & MEM_DOS_LIM) == 0);
|
||||||
ASSERT((AllocationType & MEM_RESERVE) == 0);
|
ASSERT((AllocationType & MEM_RESERVE) == 0);
|
||||||
|
@ -708,7 +707,7 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
||||||
{
|
{
|
||||||
/* A size was specified, align it to a 64K boundary */
|
/* A size was specified, align it to a 64K boundary */
|
||||||
*ViewSize += SectionOffset->LowPart & (_64K - 1);
|
*ViewSize += SectionOffset->LowPart & (_64K - 1);
|
||||||
|
|
||||||
/* Align the offset as well to make this an aligned map */
|
/* Align the offset as well to make this an aligned map */
|
||||||
SectionOffset->LowPart &= ~((ULONG)_64K - 1);
|
SectionOffset->LowPart &= ~((ULONG)_64K - 1);
|
||||||
}
|
}
|
||||||
|
@ -725,11 +724,11 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
||||||
/* The offset must be in this segment's PTE chunk and it must be valid */
|
/* The offset must be in this segment's PTE chunk and it must be valid */
|
||||||
ASSERT(PteOffset < Segment->TotalNumberOfPtes);
|
ASSERT(PteOffset < Segment->TotalNumberOfPtes);
|
||||||
ASSERT(((SectionOffset->QuadPart + *ViewSize + PAGE_SIZE - 1) >> PAGE_SHIFT) >= PteOffset);
|
ASSERT(((SectionOffset->QuadPart + *ViewSize + PAGE_SIZE - 1) >> PAGE_SHIFT) >= PteOffset);
|
||||||
|
|
||||||
/* In ARM3, only one subsection is used for now. It must contain these PTEs */
|
/* In ARM3, only one subsection is used for now. It must contain these PTEs */
|
||||||
ASSERT(PteOffset < Subsection->PtesInSubsection);
|
ASSERT(PteOffset < Subsection->PtesInSubsection);
|
||||||
ASSERT(Subsection->SubsectionBase != NULL);
|
ASSERT(Subsection->SubsectionBase != NULL);
|
||||||
|
|
||||||
/* In ARM3, only MEM_COMMIT is supported for now. The PTEs must've been committed */
|
/* In ARM3, only MEM_COMMIT is supported for now. The PTEs must've been committed */
|
||||||
ASSERT(Segment->NumberOfCommittedPages >= Segment->TotalNumberOfPtes);
|
ASSERT(Segment->NumberOfCommittedPages >= Segment->TotalNumberOfPtes);
|
||||||
|
|
||||||
|
@ -768,7 +767,7 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
||||||
|
|
||||||
/* Get the ending address, which is the last piece we need for the VAD */
|
/* Get the ending address, which is the last piece we need for the VAD */
|
||||||
EndingAddress = (StartAddress + *ViewSize - 1) | (PAGE_SIZE - 1);
|
EndingAddress = (StartAddress + *ViewSize - 1) | (PAGE_SIZE - 1);
|
||||||
|
|
||||||
/* A VAD can now be allocated. Do so and zero it out */
|
/* A VAD can now be allocated. Do so and zero it out */
|
||||||
Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD), 'ldaV');
|
Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD), 'ldaV');
|
||||||
ASSERT(Vad);
|
ASSERT(Vad);
|
||||||
|
@ -796,13 +795,13 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
||||||
/* Make sure the last PTE is valid and still within the subsection */
|
/* Make sure the last PTE is valid and still within the subsection */
|
||||||
ASSERT(PteOffset < Subsection->PtesInSubsection);
|
ASSERT(PteOffset < Subsection->PtesInSubsection);
|
||||||
ASSERT(Vad->FirstPrototypePte <= Vad->LastContiguousPte);
|
ASSERT(Vad->FirstPrototypePte <= Vad->LastContiguousPte);
|
||||||
|
|
||||||
/* FIXME: Should setup VAD bitmap */
|
/* FIXME: Should setup VAD bitmap */
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
/* Pretend as if we own the working set */
|
/* Pretend as if we own the working set */
|
||||||
MiLockProcessWorkingSet(Process, Thread);
|
MiLockProcessWorkingSet(Process, Thread);
|
||||||
|
|
||||||
/* Insert the VAD */
|
/* Insert the VAD */
|
||||||
MiInsertVad(Vad, Process);
|
MiInsertVad(Vad, Process);
|
||||||
|
|
||||||
|
@ -836,7 +835,7 @@ MiCreatePagingFileMap(OUT PSEGMENT *Segment,
|
||||||
|
|
||||||
/* No large pages in ARM3 yet */
|
/* No large pages in ARM3 yet */
|
||||||
ASSERT((AllocationAttributes & SEC_LARGE_PAGES) == 0);
|
ASSERT((AllocationAttributes & SEC_LARGE_PAGES) == 0);
|
||||||
|
|
||||||
/* Pagefile-backed sections need a known size */
|
/* Pagefile-backed sections need a known size */
|
||||||
if (!(*MaximumSize)) return STATUS_INVALID_PARAMETER_4;
|
if (!(*MaximumSize)) return STATUS_INVALID_PARAMETER_4;
|
||||||
|
|
||||||
|
@ -861,7 +860,7 @@ MiCreatePagingFileMap(OUT PSEGMENT *Segment,
|
||||||
'tSmM');
|
'tSmM');
|
||||||
ASSERT(NewSegment);
|
ASSERT(NewSegment);
|
||||||
*Segment = NewSegment;
|
*Segment = NewSegment;
|
||||||
|
|
||||||
/* Now allocate the control area, which has the subsection structure */
|
/* Now allocate the control area, which has the subsection structure */
|
||||||
ControlArea = ExAllocatePoolWithTag(NonPagedPool,
|
ControlArea = ExAllocatePoolWithTag(NonPagedPool,
|
||||||
sizeof(CONTROL_AREA) + sizeof(SUBSECTION),
|
sizeof(CONTROL_AREA) + sizeof(SUBSECTION),
|
||||||
|
@ -899,14 +898,14 @@ MiCreatePagingFileMap(OUT PSEGMENT *Segment,
|
||||||
|
|
||||||
/* The subsection's base address is the first Prototype PTE in the segment */
|
/* The subsection's base address is the first Prototype PTE in the segment */
|
||||||
Subsection->SubsectionBase = PointerPte;
|
Subsection->SubsectionBase = PointerPte;
|
||||||
|
|
||||||
/* Start with an empty PTE, unless this is a commit operation */
|
/* Start with an empty PTE, unless this is a commit operation */
|
||||||
TempPte.u.Long = 0;
|
TempPte.u.Long = 0;
|
||||||
if (AllocationAttributes & SEC_COMMIT)
|
if (AllocationAttributes & SEC_COMMIT)
|
||||||
{
|
{
|
||||||
/* In which case, write down the protection mask in the Prototype PTEs */
|
/* In which case, write down the protection mask in the Prototype PTEs */
|
||||||
TempPte.u.Soft.Protection = ProtectionMask;
|
TempPte.u.Soft.Protection = ProtectionMask;
|
||||||
|
|
||||||
/* For accounting, also mark these pages as being committed */
|
/* For accounting, also mark these pages as being committed */
|
||||||
NewSegment->NumberOfCommittedPages = PteCount;
|
NewSegment->NumberOfCommittedPages = PteCount;
|
||||||
}
|
}
|
||||||
|
@ -926,7 +925,7 @@ MmGetFileObjectForSection(IN PVOID SectionObject)
|
||||||
PSECTION_OBJECT Section;
|
PSECTION_OBJECT Section;
|
||||||
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||||
ASSERT(SectionObject != NULL);
|
ASSERT(SectionObject != NULL);
|
||||||
|
|
||||||
/* Check if it's an ARM3, or ReactOS section */
|
/* Check if it's an ARM3, or ReactOS section */
|
||||||
if ((ULONG_PTR)SectionObject & 1)
|
if ((ULONG_PTR)SectionObject & 1)
|
||||||
{
|
{
|
||||||
|
@ -947,7 +946,7 @@ MmGetFileNameForFileObject(IN PFILE_OBJECT FileObject,
|
||||||
POBJECT_NAME_INFORMATION ObjectNameInfo;
|
POBJECT_NAME_INFORMATION ObjectNameInfo;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG ReturnLength;
|
ULONG ReturnLength;
|
||||||
|
|
||||||
/* Allocate memory for our structure */
|
/* Allocate memory for our structure */
|
||||||
ObjectNameInfo = ExAllocatePoolWithTag(PagedPool, 1024, ' mM');
|
ObjectNameInfo = ExAllocatePoolWithTag(PagedPool, 1024, ' mM');
|
||||||
if (!ObjectNameInfo) return STATUS_NO_MEMORY;
|
if (!ObjectNameInfo) return STATUS_NO_MEMORY;
|
||||||
|
@ -1038,7 +1037,7 @@ InvalidAddress:
|
||||||
|
|
||||||
/* Unlock address space */
|
/* Unlock address space */
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
|
|
||||||
/* Get the filename of the section */
|
/* Get the filename of the section */
|
||||||
Status = MmGetFileNameForSection(Section, &ModuleNameInformation);
|
Status = MmGetFileNameForSection(Section, &ModuleNameInformation);
|
||||||
}
|
}
|
||||||
|
@ -1047,7 +1046,7 @@ InvalidAddress:
|
||||||
/* Get the VAD */
|
/* Get the VAD */
|
||||||
Vad = MiLocateAddress(Address);
|
Vad = MiLocateAddress(Address);
|
||||||
if (!Vad) goto InvalidAddress;
|
if (!Vad) goto InvalidAddress;
|
||||||
|
|
||||||
/* Make sure it's not a VM VAD */
|
/* Make sure it's not a VM VAD */
|
||||||
if (Vad->u.VadFlags.PrivateMemory == 1)
|
if (Vad->u.VadFlags.PrivateMemory == 1)
|
||||||
{
|
{
|
||||||
|
@ -1056,22 +1055,22 @@ NotSection:
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
return STATUS_SECTION_NOT_IMAGE;
|
return STATUS_SECTION_NOT_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the control area */
|
/* Get the control area */
|
||||||
ControlArea = Vad->ControlArea;
|
ControlArea = Vad->ControlArea;
|
||||||
if (!(ControlArea) || !(ControlArea->u.Flags.Image)) goto NotSection;
|
if (!(ControlArea) || !(ControlArea->u.Flags.Image)) goto NotSection;
|
||||||
|
|
||||||
/* Get the file object */
|
/* Get the file object */
|
||||||
FileObject = ControlArea->FilePointer;
|
FileObject = ControlArea->FilePointer;
|
||||||
ASSERT(FileObject != NULL);
|
ASSERT(FileObject != NULL);
|
||||||
ObReferenceObject(FileObject);
|
ObReferenceObject(FileObject);
|
||||||
|
|
||||||
/* Unlock address space */
|
/* Unlock address space */
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
|
|
||||||
/* Get the filename of the file object */
|
/* Get the filename of the file object */
|
||||||
Status = MmGetFileNameForFileObject(FileObject, &ModuleNameInformation);
|
Status = MmGetFileNameForFileObject(FileObject, &ModuleNameInformation);
|
||||||
|
|
||||||
/* Dereference it */
|
/* Dereference it */
|
||||||
ObDereferenceObject(FileObject);
|
ObDereferenceObject(FileObject);
|
||||||
}
|
}
|
||||||
|
@ -1092,7 +1091,7 @@ NotSection:
|
||||||
ExFreePoolWithTag(ModuleNameInformation, ' mM');
|
ExFreePoolWithTag(ModuleNameInformation, ' mM');
|
||||||
DPRINT("Found ModuleName %S by address %p\n", ModuleName->Buffer, Address);
|
DPRINT("Found ModuleName %S by address %p\n", ModuleName->Buffer, Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return status */
|
/* Return status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -1174,7 +1173,7 @@ MmCreateArm3Section(OUT PVOID *SectionObject,
|
||||||
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
|
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
|
||||||
ASSERT(ControlArea->u.Flags.Rom == 0);
|
ASSERT(ControlArea->u.Flags.Rom == 0);
|
||||||
ASSERT(ControlArea->u.Flags.WasPurged == 0);
|
ASSERT(ControlArea->u.Flags.WasPurged == 0);
|
||||||
|
|
||||||
/* A pagefile-backed mapping only has one subsection, and this is all ARM3 supports */
|
/* A pagefile-backed mapping only has one subsection, and this is all ARM3 supports */
|
||||||
Subsection = (PSUBSECTION)(ControlArea + 1);
|
Subsection = (PSUBSECTION)(ControlArea + 1);
|
||||||
ASSERT(Subsection->NextSubsection == NULL);
|
ASSERT(Subsection->NextSubsection == NULL);
|
||||||
|
@ -1228,15 +1227,15 @@ MmMapViewOfArm3Section(IN PVOID SectionObject,
|
||||||
/* Get the segment and control area */
|
/* Get the segment and control area */
|
||||||
Section = (PSECTION)SectionObject;
|
Section = (PSECTION)SectionObject;
|
||||||
ControlArea = Section->Segment->ControlArea;
|
ControlArea = Section->Segment->ControlArea;
|
||||||
|
|
||||||
/* These flags/states are not yet supported by ARM3 */
|
/* These flags/states are not yet supported by ARM3 */
|
||||||
ASSERT(Section->u.Flags.Image == 0);
|
ASSERT(Section->u.Flags.Image == 0);
|
||||||
ASSERT(Section->u.Flags.NoCache == 0);
|
ASSERT(Section->u.Flags.NoCache == 0);
|
||||||
ASSERT(Section->u.Flags.WriteCombined == 0);
|
ASSERT(Section->u.Flags.WriteCombined == 0);
|
||||||
ASSERT((AllocationType & MEM_RESERVE) == 0);
|
ASSERT((AllocationType & MEM_RESERVE) == 0);
|
||||||
ASSERT(ControlArea->u.Flags.PhysicalMemory == 0);
|
ASSERT(ControlArea->u.Flags.PhysicalMemory == 0);
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* FIXME: Check if the mapping protection is compatible with the create */
|
/* FIXME: Check if the mapping protection is compatible with the create */
|
||||||
if (!MiIsProtectionCompatible(Section->InitialPageProtection, Protect))
|
if (!MiIsProtectionCompatible(Section->InitialPageProtection, Protect))
|
||||||
|
@ -1296,7 +1295,7 @@ MmMapViewOfArm3Section(IN PVOID SectionObject,
|
||||||
DPRINT1("The protection is invalid\n");
|
DPRINT1("The protection is invalid\n");
|
||||||
return STATUS_INVALID_PAGE_PROTECTION;
|
return STATUS_INVALID_PAGE_PROTECTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We only handle pagefile-backed sections, which cannot be writecombined */
|
/* We only handle pagefile-backed sections, which cannot be writecombined */
|
||||||
if (Protect & PAGE_WRITECOMBINE)
|
if (Protect & PAGE_WRITECOMBINE)
|
||||||
{
|
{
|
||||||
|
@ -1310,7 +1309,7 @@ MmMapViewOfArm3Section(IN PVOID SectionObject,
|
||||||
KeStackAttachProcess(&Process->Pcb, &ApcState);
|
KeStackAttachProcess(&Process->Pcb, &ApcState);
|
||||||
Attached = TRUE;
|
Attached = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the address space and make sure the process is alive */
|
/* Lock the address space and make sure the process is alive */
|
||||||
MmLockAddressSpace(&Process->Vm);
|
MmLockAddressSpace(&Process->Vm);
|
||||||
if (!Process->VmDeleted)
|
if (!Process->VmDeleted)
|
||||||
|
@ -1334,7 +1333,7 @@ MmMapViewOfArm3Section(IN PVOID SectionObject,
|
||||||
DPRINT1("The process is dying\n");
|
DPRINT1("The process is dying\n");
|
||||||
Status = STATUS_PROCESS_IS_TERMINATING;
|
Status = STATUS_PROCESS_IS_TERMINATING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the address space and detatch if needed, then return status */
|
/* Unlock the address space and detatch if needed, then return status */
|
||||||
MmUnlockAddressSpace(&Process->Vm);
|
MmUnlockAddressSpace(&Process->Vm);
|
||||||
if (Attached) KeUnstackDetachProcess(&ApcState);
|
if (Attached) KeUnstackDetachProcess(&ApcState);
|
||||||
|
@ -1454,9 +1453,9 @@ NtCreateSection(OUT PHANDLE SectionHandle,
|
||||||
FileHandle,
|
FileHandle,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
/* FIXME: Should zero last page for a file mapping */
|
/* FIXME: Should zero last page for a file mapping */
|
||||||
|
|
||||||
/* Now insert the object */
|
/* Now insert the object */
|
||||||
Status = ObInsertObject(SectionObject,
|
Status = ObInsertObject(SectionObject,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -1558,7 +1557,7 @@ NtMapViewOfSection(IN HANDLE SectionHandle,
|
||||||
ACCESS_MASK DesiredAccess;
|
ACCESS_MASK DesiredAccess;
|
||||||
ULONG ProtectionMask;
|
ULONG ProtectionMask;
|
||||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
|
|
||||||
/* Check for invalid zero bits */
|
/* Check for invalid zero bits */
|
||||||
if (ZeroBits > 21) // per-arch?
|
if (ZeroBits > 21) // per-arch?
|
||||||
{
|
{
|
||||||
|
@ -1572,7 +1571,7 @@ NtMapViewOfSection(IN HANDLE SectionHandle,
|
||||||
DPRINT1("Invalid inherit disposition\n");
|
DPRINT1("Invalid inherit disposition\n");
|
||||||
return STATUS_INVALID_PARAMETER_8;
|
return STATUS_INVALID_PARAMETER_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allow only valid allocation types */
|
/* Allow only valid allocation types */
|
||||||
if ((AllocationType & ~(MEM_TOP_DOWN | MEM_LARGE_PAGES | MEM_DOS_LIM |
|
if ((AllocationType & ~(MEM_TOP_DOWN | MEM_LARGE_PAGES | MEM_DOS_LIM |
|
||||||
SEC_NO_CHANGE | MEM_RESERVE)))
|
SEC_NO_CHANGE | MEM_RESERVE)))
|
||||||
|
@ -1605,7 +1604,7 @@ NtMapViewOfSection(IN HANDLE SectionHandle,
|
||||||
ProbeForWritePointer(BaseAddress);
|
ProbeForWritePointer(BaseAddress);
|
||||||
ProbeForWriteSize_t(ViewSize);
|
ProbeForWriteSize_t(ViewSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if a section offset was given */
|
/* Check if a section offset was given */
|
||||||
if (SectionOffset)
|
if (SectionOffset)
|
||||||
{
|
{
|
||||||
|
@ -1613,7 +1612,7 @@ NtMapViewOfSection(IN HANDLE SectionHandle,
|
||||||
if (PreviousMode != KernelMode) ProbeForWriteLargeInteger(SectionOffset);
|
if (PreviousMode != KernelMode) ProbeForWriteLargeInteger(SectionOffset);
|
||||||
SafeSectionOffset = *SectionOffset;
|
SafeSectionOffset = *SectionOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Capture the other parameters */
|
/* Capture the other parameters */
|
||||||
SafeBaseAddress = *BaseAddress;
|
SafeBaseAddress = *BaseAddress;
|
||||||
SafeViewSize = *ViewSize;
|
SafeViewSize = *ViewSize;
|
||||||
|
@ -1645,7 +1644,7 @@ NtMapViewOfSection(IN HANDLE SectionHandle,
|
||||||
DPRINT1("Invalid zero bits\n");
|
DPRINT1("Invalid zero bits\n");
|
||||||
return STATUS_INVALID_PARAMETER_4;
|
return STATUS_INVALID_PARAMETER_4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reference the process */
|
/* Reference the process */
|
||||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||||
PROCESS_VM_OPERATION,
|
PROCESS_VM_OPERATION,
|
||||||
|
@ -1667,7 +1666,7 @@ NtMapViewOfSection(IN HANDLE SectionHandle,
|
||||||
ObDereferenceObject(Process);
|
ObDereferenceObject(Process);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now do the actual mapping */
|
/* Now do the actual mapping */
|
||||||
Status = MmMapViewOfSection(Section,
|
Status = MmMapViewOfSection(Section,
|
||||||
Process,
|
Process,
|
||||||
|
@ -1692,7 +1691,7 @@ NtMapViewOfSection(IN HANDLE SectionHandle,
|
||||||
SafeSectionOffset.LowPart,
|
SafeSectionOffset.LowPart,
|
||||||
SafeViewSize);
|
SafeViewSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return data only on success */
|
/* Return data only on success */
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -1744,7 +1743,7 @@ NtUnmapViewOfSection(IN HANDLE ProcessHandle,
|
||||||
|
|
||||||
/* Unmap the view */
|
/* Unmap the view */
|
||||||
Status = MmUnmapViewOfSection(Process, BaseAddress);
|
Status = MmUnmapViewOfSection(Process, BaseAddress);
|
||||||
|
|
||||||
/* Dereference the process and return status */
|
/* Dereference the process and return status */
|
||||||
ObDereferenceObject(Process);
|
ObDereferenceObject(Process);
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -1782,7 +1781,7 @@ NtExtendSection(IN HANDLE SectionHandle,
|
||||||
/* Just read the size directly */
|
/* Just read the size directly */
|
||||||
SafeNewMaximumSize = *NewMaximumSize;
|
SafeNewMaximumSize = *NewMaximumSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reference the section */
|
/* Reference the section */
|
||||||
Status = ObReferenceObjectByHandle(SectionHandle,
|
Status = ObReferenceObjectByHandle(SectionHandle,
|
||||||
SECTION_EXTEND_SIZE,
|
SECTION_EXTEND_SIZE,
|
||||||
|
@ -1799,12 +1798,12 @@ NtExtendSection(IN HANDLE SectionHandle,
|
||||||
ObDereferenceObject(Section);
|
ObDereferenceObject(Section);
|
||||||
return STATUS_SECTION_NOT_EXTENDED;
|
return STATUS_SECTION_NOT_EXTENDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Do the work */
|
/* FIXME: Do the work */
|
||||||
|
|
||||||
/* Dereference the section */
|
/* Dereference the section */
|
||||||
ObDereferenceObject(Section);
|
ObDereferenceObject(Section);
|
||||||
|
|
||||||
/* Enter SEH */
|
/* Enter SEH */
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
|
@ -1816,7 +1815,7 @@ NtExtendSection(IN HANDLE SectionHandle,
|
||||||
/* Nothing to do */
|
/* Nothing to do */
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
/* Return the status */
|
/* Return the status */
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 16 "ARM³::LOADER"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -112,7 +111,7 @@ MiLoadImageSection(IN OUT PVOID *SectionPtr,
|
||||||
|
|
||||||
/* Not session load, shouldn't have an entry */
|
/* Not session load, shouldn't have an entry */
|
||||||
ASSERT(LdrEntry == NULL);
|
ASSERT(LdrEntry == NULL);
|
||||||
|
|
||||||
/* Attach to the system process */
|
/* Attach to the system process */
|
||||||
KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
|
KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
|
||||||
|
|
||||||
|
@ -154,12 +153,12 @@ MiLoadImageSection(IN OUT PVOID *SectionPtr,
|
||||||
KeUnstackDetachProcess(&ApcState);
|
KeUnstackDetachProcess(&ApcState);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reserve system PTEs needed */
|
/* Reserve system PTEs needed */
|
||||||
PteCount = ROUND_TO_PAGES(Section->ImageSection->ImageSize) >> PAGE_SHIFT;
|
PteCount = ROUND_TO_PAGES(Section->ImageSection->ImageSize) >> PAGE_SHIFT;
|
||||||
PointerPte = MiReserveSystemPtes(PteCount, SystemPteSpace);
|
PointerPte = MiReserveSystemPtes(PteCount, SystemPteSpace);
|
||||||
if (!PointerPte) return STATUS_INSUFFICIENT_RESOURCES;
|
if (!PointerPte) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
/* New driver base */
|
/* New driver base */
|
||||||
LastPte = PointerPte + PteCount;
|
LastPte = PointerPte + PteCount;
|
||||||
DriverBase = MiPteToAddress(PointerPte);
|
DriverBase = MiPteToAddress(PointerPte);
|
||||||
|
@ -182,7 +181,7 @@ MiLoadImageSection(IN OUT PVOID *SectionPtr,
|
||||||
pos = wcsrchr(FileName->Buffer, '\\');
|
pos = wcsrchr(FileName->Buffer, '\\');
|
||||||
len = wcslen(pos) * sizeof(WCHAR);
|
len = wcslen(pos) * sizeof(WCHAR);
|
||||||
if (pos) snprintf(MI_PFN_CURRENT_PROCESS_NAME, min(16, len), "%S", pos);
|
if (pos) snprintf(MI_PFN_CURRENT_PROCESS_NAME, min(16, len), "%S", pos);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
TempPte.u.Hard.PageFrameNumber = MiAllocatePfn(PointerPte, MM_EXECUTE);
|
TempPte.u.Hard.PageFrameNumber = MiAllocatePfn(PointerPte, MM_EXECUTE);
|
||||||
|
|
||||||
|
@ -192,7 +191,7 @@ MiLoadImageSection(IN OUT PVOID *SectionPtr,
|
||||||
/* Move on */
|
/* Move on */
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the image */
|
/* Copy the image */
|
||||||
RtlCopyMemory(DriverBase, Base, PteCount << PAGE_SHIFT);
|
RtlCopyMemory(DriverBase, Base, PteCount << PAGE_SHIFT);
|
||||||
|
|
||||||
|
@ -386,14 +385,14 @@ MiDereferenceImports(IN PLOAD_IMPORTS ImportList)
|
||||||
/* Then there's nothing to do */
|
/* Then there's nothing to do */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for single-entry */
|
/* Check for single-entry */
|
||||||
if ((ULONG_PTR)ImportList & MM_SYSLDR_SINGLE_ENTRY)
|
if ((ULONG_PTR)ImportList & MM_SYSLDR_SINGLE_ENTRY)
|
||||||
{
|
{
|
||||||
/* Set it up */
|
/* Set it up */
|
||||||
SingleEntry.Count = 1;
|
SingleEntry.Count = 1;
|
||||||
SingleEntry.Entry[0] = (PVOID)((ULONG_PTR)ImportList &~ MM_SYSLDR_SINGLE_ENTRY);
|
SingleEntry.Entry[0] = (PVOID)((ULONG_PTR)ImportList &~ MM_SYSLDR_SINGLE_ENTRY);
|
||||||
|
|
||||||
/* Use this as the import list */
|
/* Use this as the import list */
|
||||||
ImportList = &SingleEntry;
|
ImportList = &SingleEntry;
|
||||||
}
|
}
|
||||||
|
@ -404,24 +403,24 @@ MiDereferenceImports(IN PLOAD_IMPORTS ImportList)
|
||||||
/* Get the entry */
|
/* Get the entry */
|
||||||
LdrEntry = ImportList->Entry[i];
|
LdrEntry = ImportList->Entry[i];
|
||||||
DPRINT1("%wZ <%wZ>\n", &LdrEntry->FullDllName, &LdrEntry->BaseDllName);
|
DPRINT1("%wZ <%wZ>\n", &LdrEntry->FullDllName, &LdrEntry->BaseDllName);
|
||||||
|
|
||||||
/* Skip boot loaded images */
|
/* Skip boot loaded images */
|
||||||
if (LdrEntry->LoadedImports == MM_SYSLDR_BOOT_LOADED) continue;
|
if (LdrEntry->LoadedImports == MM_SYSLDR_BOOT_LOADED) continue;
|
||||||
|
|
||||||
/* Dereference the entry */
|
/* Dereference the entry */
|
||||||
ASSERT(LdrEntry->LoadCount >= 1);
|
ASSERT(LdrEntry->LoadCount >= 1);
|
||||||
if (!--LdrEntry->LoadCount)
|
if (!--LdrEntry->LoadCount)
|
||||||
{
|
{
|
||||||
/* Save the import data in case unload fails */
|
/* Save the import data in case unload fails */
|
||||||
CurrentImports = LdrEntry->LoadedImports;
|
CurrentImports = LdrEntry->LoadedImports;
|
||||||
|
|
||||||
/* This is the last entry */
|
/* This is the last entry */
|
||||||
LdrEntry->LoadedImports = MM_SYSLDR_NO_IMPORTS;
|
LdrEntry->LoadedImports = MM_SYSLDR_NO_IMPORTS;
|
||||||
if (MiCallDllUnloadAndUnloadDll(LdrEntry))
|
if (MiCallDllUnloadAndUnloadDll(LdrEntry))
|
||||||
{
|
{
|
||||||
/* Unloading worked, parse this DLL's imports too */
|
/* Unloading worked, parse this DLL's imports too */
|
||||||
MiDereferenceImports(CurrentImports);
|
MiDereferenceImports(CurrentImports);
|
||||||
|
|
||||||
/* Check if we had valid imports */
|
/* Check if we had valid imports */
|
||||||
if ((CurrentImports != MM_SYSLDR_BOOT_LOADED) ||
|
if ((CurrentImports != MM_SYSLDR_BOOT_LOADED) ||
|
||||||
(CurrentImports != MM_SYSLDR_NO_IMPORTS) ||
|
(CurrentImports != MM_SYSLDR_NO_IMPORTS) ||
|
||||||
|
@ -438,7 +437,7 @@ MiDereferenceImports(IN PLOAD_IMPORTS ImportList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Done */
|
/* Done */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1454,7 +1453,7 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
|
|
||||||
/* Remember the original address */
|
/* Remember the original address */
|
||||||
DllBase = LdrEntry->DllBase;
|
DllBase = LdrEntry->DllBase;
|
||||||
|
|
||||||
/* Loop the PTEs */
|
/* Loop the PTEs */
|
||||||
PointerPte = StartPte;
|
PointerPte = StartPte;
|
||||||
while (PointerPte < LastPte)
|
while (PointerPte < LastPte)
|
||||||
|
@ -1464,11 +1463,11 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
|
Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
|
||||||
ASSERT(Pfn1->u3.e1.Rom == 0);
|
ASSERT(Pfn1->u3.e1.Rom == 0);
|
||||||
Pfn1->u3.e1.Modified = TRUE;
|
Pfn1->u3.e1.Modified = TRUE;
|
||||||
|
|
||||||
/* Next */
|
/* Next */
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now reserve system PTEs for the image */
|
/* Now reserve system PTEs for the image */
|
||||||
PointerPte = MiReserveSystemPtes(PteCount, SystemPteSpace);
|
PointerPte = MiReserveSystemPtes(PteCount, SystemPteSpace);
|
||||||
if (!PointerPte)
|
if (!PointerPte)
|
||||||
|
@ -1477,7 +1476,7 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
DPRINT1("[Mm0]: Couldn't allocate driver section!\n");
|
DPRINT1("[Mm0]: Couldn't allocate driver section!\n");
|
||||||
while (TRUE);
|
while (TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the new virtual address for the module */
|
/* This is the new virtual address for the module */
|
||||||
LastPte = PointerPte + PteCount;
|
LastPte = PointerPte + PteCount;
|
||||||
NewImageAddress = MiPteToAddress(PointerPte);
|
NewImageAddress = MiPteToAddress(PointerPte);
|
||||||
|
@ -1485,7 +1484,7 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
DPRINT("[Mm0]: Copying from: %p to: %p\n", DllBase, NewImageAddress);
|
DPRINT("[Mm0]: Copying from: %p to: %p\n", DllBase, NewImageAddress);
|
||||||
ASSERT(ExpInitializationPhase == 0);
|
ASSERT(ExpInitializationPhase == 0);
|
||||||
|
|
||||||
/* Loop the new driver PTEs */
|
/* Loop the new driver PTEs */
|
||||||
TempPte = ValidKernelPte;
|
TempPte = ValidKernelPte;
|
||||||
while (PointerPte < LastPte)
|
while (PointerPte < LastPte)
|
||||||
|
@ -1504,7 +1503,7 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
StartPte++;
|
StartPte++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update position */
|
/* Update position */
|
||||||
PointerPte -= PteCount;
|
PointerPte -= PteCount;
|
||||||
|
|
||||||
|
@ -1547,7 +1546,7 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)NewImageAddress +
|
LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)NewImageAddress +
|
||||||
NtHeader->OptionalHeader.AddressOfEntryPoint);
|
NtHeader->OptionalHeader.AddressOfEntryPoint);
|
||||||
LdrEntry->SizeOfImage = PteCount << PAGE_SHIFT;
|
LdrEntry->SizeOfImage = PteCount << PAGE_SHIFT;
|
||||||
|
|
||||||
/* FIXME: We'll need to fixup the PFN linkage when switching to ARM3 */
|
/* FIXME: We'll need to fixup the PFN linkage when switching to ARM3 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1568,7 +1567,7 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
ULONG_PTR DllBase, DllEnd;
|
ULONG_PTR DllBase, DllEnd;
|
||||||
ULONG Modules = 0, i, j = 0;
|
ULONG Modules = 0, i, j = 0;
|
||||||
PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
|
PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
|
||||||
|
|
||||||
/* Initialize variables */
|
/* Initialize variables */
|
||||||
KernelEntry = HalEntry = LastEntry = NULL;
|
KernelEntry = HalEntry = LastEntry = NULL;
|
||||||
|
|
||||||
|
@ -1592,7 +1591,7 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
/* Found it */
|
/* Found it */
|
||||||
HalEntry = LdrEntry;
|
HalEntry = LdrEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if this is a driver DLL */
|
/* Check if this is a driver DLL */
|
||||||
if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL)
|
if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL)
|
||||||
{
|
{
|
||||||
|
@ -1611,9 +1610,9 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* No referencing needed */
|
/* No referencing needed */
|
||||||
LdrEntry->LoadCount = 0;
|
LdrEntry->LoadCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remember this came from the loader */
|
/* Remember this came from the loader */
|
||||||
LdrEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
|
LdrEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
|
||||||
|
|
||||||
|
@ -1621,10 +1620,10 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
NextEntry = NextEntry->Flink;
|
NextEntry = NextEntry->Flink;
|
||||||
Modules++;
|
Modules++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We must have at least found the kernel and HAL */
|
/* We must have at least found the kernel and HAL */
|
||||||
if (!(HalEntry) || (!KernelEntry)) return STATUS_NOT_FOUND;
|
if (!(HalEntry) || (!KernelEntry)) return STATUS_NOT_FOUND;
|
||||||
|
|
||||||
/* Allocate the list */
|
/* Allocate the list */
|
||||||
EntryArray = ExAllocatePoolWithTag(PagedPool, Modules * sizeof(PVOID), 'TDmM');
|
EntryArray = ExAllocatePoolWithTag(PagedPool, Modules * sizeof(PVOID), 'TDmM');
|
||||||
if (!EntryArray) return STATUS_INSUFFICIENT_RESOURCES;
|
if (!EntryArray) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
@ -1643,7 +1642,7 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
TRUE,
|
TRUE,
|
||||||
IMAGE_DIRECTORY_ENTRY_IAT,
|
IMAGE_DIRECTORY_ENTRY_IAT,
|
||||||
&ImportSize);
|
&ImportSize);
|
||||||
if (!ImageThunk)
|
if (!ImageThunk)
|
||||||
#else
|
#else
|
||||||
/* Get its imports */
|
/* Get its imports */
|
||||||
ImportDescriptor = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
|
ImportDescriptor = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
|
||||||
|
@ -1658,12 +1657,12 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
NextEntry = NextEntry->Flink;
|
NextEntry = NextEntry->Flink;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the list and count the number of IAT thunks */
|
/* Clear the list and count the number of IAT thunks */
|
||||||
RtlZeroMemory(EntryArray, Modules * sizeof(PVOID));
|
RtlZeroMemory(EntryArray, Modules * sizeof(PVOID));
|
||||||
#ifdef _WORKING_LOADER_
|
#ifdef _WORKING_LOADER_
|
||||||
ImportSize /= sizeof(ULONG_PTR);
|
ImportSize /= sizeof(ULONG_PTR);
|
||||||
|
|
||||||
/* Scan the thunks */
|
/* Scan the thunks */
|
||||||
for (i = 0, DllBase = 0, DllEnd = 0; i < ImportSize; i++, ImageThunk++)
|
for (i = 0, DllBase = 0, DllEnd = 0; i < ImportSize; i++, ImageThunk++)
|
||||||
#else
|
#else
|
||||||
|
@ -1689,7 +1688,7 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loop the loaded module list to locate this address owner */
|
/* Loop the loaded module list to locate this address owner */
|
||||||
j = 0;
|
j = 0;
|
||||||
NextEntry2 = PsLoadedModuleList.Flink;
|
NextEntry2 = PsLoadedModuleList.Flink;
|
||||||
|
@ -1699,11 +1698,11 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
LdrEntry2 = CONTAINING_RECORD(NextEntry2,
|
LdrEntry2 = CONTAINING_RECORD(NextEntry2,
|
||||||
LDR_DATA_TABLE_ENTRY,
|
LDR_DATA_TABLE_ENTRY,
|
||||||
InLoadOrderLinks);
|
InLoadOrderLinks);
|
||||||
|
|
||||||
/* Get the address range for this module */
|
/* Get the address range for this module */
|
||||||
DllBase = (ULONG_PTR)LdrEntry2->DllBase;
|
DllBase = (ULONG_PTR)LdrEntry2->DllBase;
|
||||||
DllEnd = DllBase + LdrEntry2->SizeOfImage;
|
DllEnd = DllBase + LdrEntry2->SizeOfImage;
|
||||||
|
|
||||||
/* Check if this IAT entry matches it */
|
/* Check if this IAT entry matches it */
|
||||||
if ((*ImageThunk >= DllBase) && (*ImageThunk < DllEnd))
|
if ((*ImageThunk >= DllBase) && (*ImageThunk < DllEnd))
|
||||||
{
|
{
|
||||||
|
@ -1712,12 +1711,12 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
EntryArray[j] = LdrEntry2;
|
EntryArray[j] = LdrEntry2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep searching */
|
/* Keep searching */
|
||||||
NextEntry2 = NextEntry2->Flink;
|
NextEntry2 = NextEntry2->Flink;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do we have a thunk outside the range? */
|
/* Do we have a thunk outside the range? */
|
||||||
if ((*ImageThunk < DllBase) || (*ImageThunk >= DllEnd))
|
if ((*ImageThunk < DllBase) || (*ImageThunk >= DllEnd))
|
||||||
{
|
{
|
||||||
|
@ -1729,19 +1728,19 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
LdrEntry, ImageThunk, *ImageThunk);
|
LdrEntry, ImageThunk, *ImageThunk);
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset if we hit this */
|
/* Reset if we hit this */
|
||||||
DllBase = 0;
|
DllBase = 0;
|
||||||
}
|
}
|
||||||
#ifndef _WORKING_LOADER_
|
#ifndef _WORKING_LOADER_
|
||||||
ImageThunk++;
|
ImageThunk++;
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
ImportDescriptor++;
|
ImportDescriptor++;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now scan how many imports we really have */
|
/* Now scan how many imports we really have */
|
||||||
for (i = 0, ImportSize = 0; i < Modules; i++)
|
for (i = 0, ImportSize = 0; i < Modules; i++)
|
||||||
{
|
{
|
||||||
|
@ -1755,7 +1754,7 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
ImportSize++;
|
ImportSize++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do we have any imports after all? */
|
/* Do we have any imports after all? */
|
||||||
if (!ImportSize)
|
if (!ImportSize)
|
||||||
{
|
{
|
||||||
|
@ -1776,10 +1775,10 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
LoadedImportsSize,
|
LoadedImportsSize,
|
||||||
'TDmM');
|
'TDmM');
|
||||||
ASSERT(LoadedImports);
|
ASSERT(LoadedImports);
|
||||||
|
|
||||||
/* Save the count */
|
/* Save the count */
|
||||||
LoadedImports->Count = ImportSize;
|
LoadedImports->Count = ImportSize;
|
||||||
|
|
||||||
/* Now copy all imports */
|
/* Now copy all imports */
|
||||||
for (i = 0, j = 0; i < Modules; i++)
|
for (i = 0, j = 0; i < Modules; i++)
|
||||||
{
|
{
|
||||||
|
@ -1795,25 +1794,25 @@ MiBuildImportsForBootDrivers(VOID)
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Should had as many entries as we expected */
|
/* Should had as many entries as we expected */
|
||||||
ASSERT(j == ImportSize);
|
ASSERT(j == ImportSize);
|
||||||
LdrEntry->LoadedImports = LoadedImports;
|
LdrEntry->LoadedImports = LoadedImports;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next */
|
/* Next */
|
||||||
NextEntry = NextEntry->Flink;
|
NextEntry = NextEntry->Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the initial array */
|
/* Free the initial array */
|
||||||
ExFreePool(EntryArray);
|
ExFreePool(EntryArray);
|
||||||
|
|
||||||
/* FIXME: Might not need to keep the HAL/Kernel imports around */
|
/* FIXME: Might not need to keep the HAL/Kernel imports around */
|
||||||
|
|
||||||
/* Kernel and HAL are loaded at boot */
|
/* Kernel and HAL are loaded at boot */
|
||||||
KernelEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
|
KernelEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
|
||||||
HalEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
|
HalEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
|
||||||
|
|
||||||
/* All worked well */
|
/* All worked well */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1827,7 +1826,7 @@ MiLocateKernelSections(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
|
||||||
PIMAGE_NT_HEADERS NtHeaders;
|
PIMAGE_NT_HEADERS NtHeaders;
|
||||||
PIMAGE_SECTION_HEADER SectionHeader;
|
PIMAGE_SECTION_HEADER SectionHeader;
|
||||||
ULONG Sections, Size;
|
ULONG Sections, Size;
|
||||||
|
|
||||||
/* Get the kernel section header */
|
/* Get the kernel section header */
|
||||||
DllBase = (ULONG_PTR)LdrEntry->DllBase;
|
DllBase = (ULONG_PTR)LdrEntry->DllBase;
|
||||||
NtHeaders = RtlImageNtHeader((PVOID)DllBase);
|
NtHeaders = RtlImageNtHeader((PVOID)DllBase);
|
||||||
|
@ -1839,7 +1838,7 @@ MiLocateKernelSections(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
|
||||||
{
|
{
|
||||||
/* Grab the size of the section */
|
/* Grab the size of the section */
|
||||||
Size = max(SectionHeader->SizeOfRawData, SectionHeader->Misc.VirtualSize);
|
Size = max(SectionHeader->SizeOfRawData, SectionHeader->Misc.VirtualSize);
|
||||||
|
|
||||||
/* Check for .RSRC section */
|
/* Check for .RSRC section */
|
||||||
if (*(PULONG)SectionHeader->Name == 'rsr.')
|
if (*(PULONG)SectionHeader->Name == 'rsr.')
|
||||||
{
|
{
|
||||||
|
@ -1862,7 +1861,7 @@ MiLocateKernelSections(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
|
||||||
{
|
{
|
||||||
/* Found Mm* Pool code */
|
/* Found Mm* Pool code */
|
||||||
MmPoolCodeStart = DllBase + SectionHeader->VirtualAddress;
|
MmPoolCodeStart = DllBase + SectionHeader->VirtualAddress;
|
||||||
MmPoolCodeEnd = ExPoolCodeStart + Size;
|
MmPoolCodeEnd = ExPoolCodeStart + Size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((*(PULONG)SectionHeader->Name == 'YSIM') &&
|
else if ((*(PULONG)SectionHeader->Name == 'YSIM') &&
|
||||||
|
@ -1872,7 +1871,7 @@ MiLocateKernelSections(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
|
||||||
MmPteCodeStart = DllBase + SectionHeader->VirtualAddress;
|
MmPteCodeStart = DllBase + SectionHeader->VirtualAddress;
|
||||||
MmPteCodeEnd = ExPoolCodeStart + Size;
|
MmPteCodeEnd = ExPoolCodeStart + Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep going */
|
/* Keep going */
|
||||||
Sections--;
|
Sections--;
|
||||||
SectionHeader++;
|
SectionHeader++;
|
||||||
|
@ -1900,7 +1899,7 @@ MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
LDR_DATA_TABLE_ENTRY,
|
LDR_DATA_TABLE_ENTRY,
|
||||||
InLoadOrderLinks);
|
InLoadOrderLinks);
|
||||||
PsNtosImageBase = (ULONG_PTR)LdrEntry->DllBase;
|
PsNtosImageBase = (ULONG_PTR)LdrEntry->DllBase;
|
||||||
|
|
||||||
/* Locate resource section, pool code, and system pte code */
|
/* Locate resource section, pool code, and system pte code */
|
||||||
MiLocateKernelSections(LdrEntry);
|
MiLocateKernelSections(LdrEntry);
|
||||||
|
|
||||||
|
@ -2012,11 +2011,11 @@ MiUseLargeDriverPage(IN ULONG NumberOfPtes,
|
||||||
/* Keep trying */
|
/* Keep trying */
|
||||||
NextEntry = NextEntry->Flink;
|
NextEntry = NextEntry->Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we didn't find the driver, it doesn't need large pages */
|
/* If we didn't find the driver, it doesn't need large pages */
|
||||||
if (DriverFound == FALSE) return FALSE;
|
if (DriverFound == FALSE) return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nothing to do yet */
|
/* Nothing to do yet */
|
||||||
DPRINT1("Large pages not supported!\n");
|
DPRINT1("Large pages not supported!\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -2028,13 +2027,13 @@ MiComputeDriverProtection(IN BOOLEAN SessionSpace,
|
||||||
IN ULONG SectionProtection)
|
IN ULONG SectionProtection)
|
||||||
{
|
{
|
||||||
ULONG Protection = MM_ZERO_ACCESS;
|
ULONG Protection = MM_ZERO_ACCESS;
|
||||||
|
|
||||||
/* Check if the caller gave anything */
|
/* Check if the caller gave anything */
|
||||||
if (SectionProtection)
|
if (SectionProtection)
|
||||||
{
|
{
|
||||||
/* Always turn on execute access */
|
/* Always turn on execute access */
|
||||||
SectionProtection |= IMAGE_SCN_MEM_EXECUTE;
|
SectionProtection |= IMAGE_SCN_MEM_EXECUTE;
|
||||||
|
|
||||||
/* Check if the registry setting is on or not */
|
/* Check if the registry setting is on or not */
|
||||||
if (!MmEnforceWriteProtection)
|
if (!MmEnforceWriteProtection)
|
||||||
{
|
{
|
||||||
|
@ -2042,11 +2041,11 @@ MiComputeDriverProtection(IN BOOLEAN SessionSpace,
|
||||||
SectionProtection |= (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE);
|
SectionProtection |= (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert to internal PTE flags */
|
/* Convert to internal PTE flags */
|
||||||
if (SectionProtection & IMAGE_SCN_MEM_EXECUTE) Protection |= MM_EXECUTE;
|
if (SectionProtection & IMAGE_SCN_MEM_EXECUTE) Protection |= MM_EXECUTE;
|
||||||
if (SectionProtection & IMAGE_SCN_MEM_READ) Protection |= MM_READONLY;
|
if (SectionProtection & IMAGE_SCN_MEM_READ) Protection |= MM_READONLY;
|
||||||
|
|
||||||
/* Check for write access */
|
/* Check for write access */
|
||||||
if (SectionProtection & IMAGE_SCN_MEM_WRITE)
|
if (SectionProtection & IMAGE_SCN_MEM_WRITE)
|
||||||
{
|
{
|
||||||
|
@ -2062,10 +2061,10 @@ MiComputeDriverProtection(IN BOOLEAN SessionSpace,
|
||||||
Protection = (Protection & MM_EXECUTE) ? MM_EXECUTE_READWRITE : MM_READWRITE;
|
Protection = (Protection & MM_EXECUTE) ? MM_EXECUTE_READWRITE : MM_READWRITE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there's no access at all by now, convert to internal no access flag */
|
/* If there's no access at all by now, convert to internal no access flag */
|
||||||
if (Protection == MM_ZERO_ACCESS) Protection = MM_NOACCESS;
|
if (Protection == MM_ZERO_ACCESS) Protection = MM_NOACCESS;
|
||||||
|
|
||||||
/* Return the computed PTE protection */
|
/* Return the computed PTE protection */
|
||||||
return Protection;
|
return Protection;
|
||||||
}
|
}
|
||||||
|
@ -2093,14 +2092,14 @@ MiWriteProtectSystemImage(IN PVOID ImageBase)
|
||||||
PMMPTE PointerPte, StartPte, LastPte, CurrentPte, ComboPte = NULL;
|
PMMPTE PointerPte, StartPte, LastPte, CurrentPte, ComboPte = NULL;
|
||||||
ULONG CurrentMask, CombinedMask = 0;
|
ULONG CurrentMask, CombinedMask = 0;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* No need to write protect physical memory-backed drivers (large pages) */
|
/* No need to write protect physical memory-backed drivers (large pages) */
|
||||||
if (MI_IS_PHYSICAL_ADDRESS(ImageBase)) return;
|
if (MI_IS_PHYSICAL_ADDRESS(ImageBase)) return;
|
||||||
|
|
||||||
/* Get the image headers */
|
/* Get the image headers */
|
||||||
NtHeaders = RtlImageNtHeader(ImageBase);
|
NtHeaders = RtlImageNtHeader(ImageBase);
|
||||||
if (!NtHeaders) return;
|
if (!NtHeaders) return;
|
||||||
|
|
||||||
/* Check if this is a session driver or not */
|
/* Check if this is a session driver or not */
|
||||||
if (!MI_IS_SESSION_ADDRESS(ImageBase))
|
if (!MI_IS_SESSION_ADDRESS(ImageBase))
|
||||||
{
|
{
|
||||||
|
@ -2114,13 +2113,13 @@ MiWriteProtectSystemImage(IN PVOID ImageBase)
|
||||||
DPRINT1("Session drivers not supported\n");
|
DPRINT1("Session drivers not supported\n");
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These are the only protection masks we care about */
|
/* These are the only protection masks we care about */
|
||||||
ProtectionMask = IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
|
ProtectionMask = IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
|
||||||
|
|
||||||
/* Calculate the number of pages this driver is occupying */
|
/* Calculate the number of pages this driver is occupying */
|
||||||
DriverPages = BYTES_TO_PAGES(NtHeaders->OptionalHeader.SizeOfImage);
|
DriverPages = BYTES_TO_PAGES(NtHeaders->OptionalHeader.SizeOfImage);
|
||||||
|
|
||||||
/* Get the number of sections and the first section header */
|
/* Get the number of sections and the first section header */
|
||||||
Sections = NtHeaders->FileHeader.NumberOfSections;
|
Sections = NtHeaders->FileHeader.NumberOfSections;
|
||||||
ASSERT(Sections != 0);
|
ASSERT(Sections != 0);
|
||||||
|
@ -2132,7 +2131,7 @@ MiWriteProtectSystemImage(IN PVOID ImageBase)
|
||||||
{
|
{
|
||||||
/* Get the section size */
|
/* Get the section size */
|
||||||
Size = max(Section->SizeOfRawData, Section->Misc.VirtualSize);
|
Size = max(Section->SizeOfRawData, Section->Misc.VirtualSize);
|
||||||
|
|
||||||
/* Get its virtual address */
|
/* Get its virtual address */
|
||||||
BaseAddress = (ULONG_PTR)ImageBase + Section->VirtualAddress;
|
BaseAddress = (ULONG_PTR)ImageBase + Section->VirtualAddress;
|
||||||
if (BaseAddress < CurrentAddress)
|
if (BaseAddress < CurrentAddress)
|
||||||
|
@ -2141,24 +2140,24 @@ MiWriteProtectSystemImage(IN PVOID ImageBase)
|
||||||
DPRINT1("Badly linked image!\n");
|
DPRINT1("Badly linked image!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remember the current address */
|
/* Remember the current address */
|
||||||
CurrentAddress = BaseAddress + Size - 1;
|
CurrentAddress = BaseAddress + Size - 1;
|
||||||
|
|
||||||
/* Next */
|
/* Next */
|
||||||
Sections--;
|
Sections--;
|
||||||
Section++;
|
Section++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the number of sections and the first section header */
|
/* Get the number of sections and the first section header */
|
||||||
Sections = NtHeaders->FileHeader.NumberOfSections;
|
Sections = NtHeaders->FileHeader.NumberOfSections;
|
||||||
ASSERT(Sections != 0);
|
ASSERT(Sections != 0);
|
||||||
Section = IMAGE_FIRST_SECTION(NtHeaders);
|
Section = IMAGE_FIRST_SECTION(NtHeaders);
|
||||||
|
|
||||||
/* Set the address at the end to initialize the loop */
|
/* Set the address at the end to initialize the loop */
|
||||||
CurrentAddress = (ULONG_PTR)Section + Sections - 1;
|
CurrentAddress = (ULONG_PTR)Section + Sections - 1;
|
||||||
CurrentProtection = IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ;
|
CurrentProtection = IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ;
|
||||||
|
|
||||||
/* Set the PTE points for the image, and loop its sections */
|
/* Set the PTE points for the image, and loop its sections */
|
||||||
StartPte = MiAddressToPte(ImageBase);
|
StartPte = MiAddressToPte(ImageBase);
|
||||||
LastPte = StartPte + DriverPages;
|
LastPte = StartPte + DriverPages;
|
||||||
|
@ -2166,97 +2165,97 @@ MiWriteProtectSystemImage(IN PVOID ImageBase)
|
||||||
{
|
{
|
||||||
/* Get the section size */
|
/* Get the section size */
|
||||||
Size = max(Section->SizeOfRawData, Section->Misc.VirtualSize);
|
Size = max(Section->SizeOfRawData, Section->Misc.VirtualSize);
|
||||||
|
|
||||||
/* Get its virtual address and PTE */
|
/* Get its virtual address and PTE */
|
||||||
BaseAddress = (ULONG_PTR)ImageBase + Section->VirtualAddress;
|
BaseAddress = (ULONG_PTR)ImageBase + Section->VirtualAddress;
|
||||||
PointerPte = MiAddressToPte(BaseAddress);
|
PointerPte = MiAddressToPte(BaseAddress);
|
||||||
|
|
||||||
/* Check if we were already protecting a run, and found a new run */
|
/* Check if we were already protecting a run, and found a new run */
|
||||||
if ((ComboPte) && (PointerPte > ComboPte))
|
if ((ComboPte) && (PointerPte > ComboPte))
|
||||||
{
|
{
|
||||||
/* Compute protection */
|
/* Compute protection */
|
||||||
CombinedMask = MiComputeDriverProtection(FALSE, CombinedProtection);
|
CombinedMask = MiComputeDriverProtection(FALSE, CombinedProtection);
|
||||||
|
|
||||||
/* Set it */
|
/* Set it */
|
||||||
MiSetSystemCodeProtection(ComboPte, ComboPte, CombinedMask);
|
MiSetSystemCodeProtection(ComboPte, ComboPte, CombinedMask);
|
||||||
|
|
||||||
/* Check for overlap */
|
/* Check for overlap */
|
||||||
if (ComboPte == StartPte) StartPte++;
|
if (ComboPte == StartPte) StartPte++;
|
||||||
|
|
||||||
/* One done, reset variables */
|
/* One done, reset variables */
|
||||||
ComboPte = NULL;
|
ComboPte = NULL;
|
||||||
CombinedProtection = 0;
|
CombinedProtection = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Break out when needed */
|
/* Break out when needed */
|
||||||
if (PointerPte >= LastPte) break;
|
if (PointerPte >= LastPte) break;
|
||||||
|
|
||||||
/* Get the requested protection from the image header */
|
/* Get the requested protection from the image header */
|
||||||
SectionProtection = Section->Characteristics & ProtectionMask;
|
SectionProtection = Section->Characteristics & ProtectionMask;
|
||||||
if (SectionProtection == CurrentProtection)
|
if (SectionProtection == CurrentProtection)
|
||||||
{
|
{
|
||||||
/* Same protection, so merge the request */
|
/* Same protection, so merge the request */
|
||||||
CurrentAddress = BaseAddress + Size - 1;
|
CurrentAddress = BaseAddress + Size - 1;
|
||||||
|
|
||||||
/* Next */
|
/* Next */
|
||||||
Sections--;
|
Sections--;
|
||||||
Section++;
|
Section++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is now a new section, so close up the old one */
|
/* This is now a new section, so close up the old one */
|
||||||
CurrentPte = MiAddressToPte(CurrentAddress);
|
CurrentPte = MiAddressToPte(CurrentAddress);
|
||||||
|
|
||||||
/* Check for overlap */
|
/* Check for overlap */
|
||||||
if (CurrentPte == PointerPte)
|
if (CurrentPte == PointerPte)
|
||||||
{
|
{
|
||||||
/* Skip the last PTE, since it overlaps with us */
|
/* Skip the last PTE, since it overlaps with us */
|
||||||
CurrentPte--;
|
CurrentPte--;
|
||||||
|
|
||||||
/* And set the PTE we will merge with */
|
/* And set the PTE we will merge with */
|
||||||
ASSERT((ComboPte == NULL) || (ComboPte == PointerPte));
|
ASSERT((ComboPte == NULL) || (ComboPte == PointerPte));
|
||||||
ComboPte = PointerPte;
|
ComboPte = PointerPte;
|
||||||
|
|
||||||
/* Get the most flexible protection by merging both */
|
/* Get the most flexible protection by merging both */
|
||||||
CombinedMask |= (SectionProtection | CurrentProtection);
|
CombinedMask |= (SectionProtection | CurrentProtection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loop any PTEs left */
|
/* Loop any PTEs left */
|
||||||
if (CurrentPte >= StartPte)
|
if (CurrentPte >= StartPte)
|
||||||
{
|
{
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
ASSERT(StartPte < LastPte);
|
ASSERT(StartPte < LastPte);
|
||||||
|
|
||||||
/* Make sure we don't overflow past the last PTE in the driver */
|
/* Make sure we don't overflow past the last PTE in the driver */
|
||||||
if (CurrentPte >= LastPte) CurrentPte = LastPte - 1;
|
if (CurrentPte >= LastPte) CurrentPte = LastPte - 1;
|
||||||
ASSERT(CurrentPte >= StartPte);
|
ASSERT(CurrentPte >= StartPte);
|
||||||
|
|
||||||
/* Compute the protection and set it */
|
/* Compute the protection and set it */
|
||||||
CurrentMask = MiComputeDriverProtection(FALSE, CurrentProtection);
|
CurrentMask = MiComputeDriverProtection(FALSE, CurrentProtection);
|
||||||
MiSetSystemCodeProtection(StartPte, CurrentPte, CurrentMask);
|
MiSetSystemCodeProtection(StartPte, CurrentPte, CurrentMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set new state */
|
/* Set new state */
|
||||||
StartPte = PointerPte;
|
StartPte = PointerPte;
|
||||||
CurrentAddress = BaseAddress + Size - 1;
|
CurrentAddress = BaseAddress + Size - 1;
|
||||||
CurrentProtection = SectionProtection;
|
CurrentProtection = SectionProtection;
|
||||||
|
|
||||||
/* Next */
|
/* Next */
|
||||||
Sections--;
|
Sections--;
|
||||||
Section++;
|
Section++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is there a leftover section to merge? */
|
/* Is there a leftover section to merge? */
|
||||||
if (ComboPte)
|
if (ComboPte)
|
||||||
{
|
{
|
||||||
/* Compute and set the protection */
|
/* Compute and set the protection */
|
||||||
CombinedMask = MiComputeDriverProtection(FALSE, CombinedProtection);
|
CombinedMask = MiComputeDriverProtection(FALSE, CombinedProtection);
|
||||||
MiSetSystemCodeProtection(ComboPte, ComboPte, CombinedMask);
|
MiSetSystemCodeProtection(ComboPte, ComboPte, CombinedMask);
|
||||||
|
|
||||||
/* Handle overlap */
|
/* Handle overlap */
|
||||||
if (ComboPte == StartPte) StartPte++;
|
if (ComboPte == StartPte) StartPte++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally, handle the last section */
|
/* Finally, handle the last section */
|
||||||
CurrentPte = MiAddressToPte(CurrentAddress);
|
CurrentPte = MiAddressToPte(CurrentAddress);
|
||||||
if ((StartPte < LastPte) && (CurrentPte >= StartPte))
|
if ((StartPte < LastPte) && (CurrentPte >= StartPte))
|
||||||
|
@ -2264,7 +2263,7 @@ MiWriteProtectSystemImage(IN PVOID ImageBase)
|
||||||
/* Handle overlap */
|
/* Handle overlap */
|
||||||
if (CurrentPte >= LastPte) CurrentPte = LastPte - 1;
|
if (CurrentPte >= LastPte) CurrentPte = LastPte - 1;
|
||||||
ASSERT(CurrentPte >= StartPte);
|
ASSERT(CurrentPte >= StartPte);
|
||||||
|
|
||||||
/* Compute and set the protection */
|
/* Compute and set the protection */
|
||||||
CurrentMask = MiComputeDriverProtection(FALSE, CurrentProtection);
|
CurrentMask = MiComputeDriverProtection(FALSE, CurrentProtection);
|
||||||
MiSetSystemCodeProtection(StartPte, CurrentPte, CurrentMask);
|
MiSetSystemCodeProtection(StartPte, CurrentPte, CurrentMask);
|
||||||
|
@ -2281,17 +2280,17 @@ MiSetPagingOfDriver(IN PMMPTE PointerPte,
|
||||||
PFN_NUMBER PageCount = 0, PageFrameIndex;
|
PFN_NUMBER PageCount = 0, PageFrameIndex;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Get the driver's base address */
|
/* Get the driver's base address */
|
||||||
ImageBase = MiPteToAddress(PointerPte);
|
ImageBase = MiPteToAddress(PointerPte);
|
||||||
ASSERT(MI_IS_SESSION_IMAGE_ADDRESS(ImageBase) == FALSE);
|
ASSERT(MI_IS_SESSION_IMAGE_ADDRESS(ImageBase) == FALSE);
|
||||||
|
|
||||||
/* If this is a large page, it's stuck in physical memory */
|
/* If this is a large page, it's stuck in physical memory */
|
||||||
if (MI_IS_PHYSICAL_ADDRESS(ImageBase)) return;
|
if (MI_IS_PHYSICAL_ADDRESS(ImageBase)) return;
|
||||||
|
|
||||||
/* Lock the working set */
|
/* Lock the working set */
|
||||||
MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
|
MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
|
||||||
|
|
||||||
/* Loop the PTEs */
|
/* Loop the PTEs */
|
||||||
while (PointerPte <= LastPte)
|
while (PointerPte <= LastPte)
|
||||||
{
|
{
|
||||||
|
@ -2301,18 +2300,18 @@ MiSetPagingOfDriver(IN PMMPTE PointerPte,
|
||||||
PageFrameIndex = PFN_FROM_PTE(PointerPte);
|
PageFrameIndex = PFN_FROM_PTE(PointerPte);
|
||||||
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
||||||
ASSERT(Pfn1->u2.ShareCount == 1);
|
ASSERT(Pfn1->u2.ShareCount == 1);
|
||||||
|
|
||||||
/* No working sets in ReactOS yet */
|
/* No working sets in ReactOS yet */
|
||||||
PageCount++;
|
PageCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageBase = (PVOID)((ULONG_PTR)ImageBase + PAGE_SIZE);
|
ImageBase = (PVOID)((ULONG_PTR)ImageBase + PAGE_SIZE);
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the working set */
|
/* Release the working set */
|
||||||
MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
|
MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
|
||||||
|
|
||||||
/* Do we have any driver pages? */
|
/* Do we have any driver pages? */
|
||||||
if (PageCount)
|
if (PageCount)
|
||||||
{
|
{
|
||||||
|
@ -2331,16 +2330,16 @@ MiEnablePagingOfDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
|
||||||
PIMAGE_SECTION_HEADER Section;
|
PIMAGE_SECTION_HEADER Section;
|
||||||
PMMPTE PointerPte = NULL, LastPte = NULL;
|
PMMPTE PointerPte = NULL, LastPte = NULL;
|
||||||
if (MmDisablePagingExecutive) return;
|
if (MmDisablePagingExecutive) return;
|
||||||
|
|
||||||
/* Get the driver base address and its NT header */
|
/* Get the driver base address and its NT header */
|
||||||
ImageBase = (ULONG_PTR)LdrEntry->DllBase;
|
ImageBase = (ULONG_PTR)LdrEntry->DllBase;
|
||||||
NtHeaders = RtlImageNtHeader((PVOID)ImageBase);
|
NtHeaders = RtlImageNtHeader((PVOID)ImageBase);
|
||||||
if (!NtHeaders) return;
|
if (!NtHeaders) return;
|
||||||
|
|
||||||
/* Get the sections and their alignment */
|
/* Get the sections and their alignment */
|
||||||
Sections = NtHeaders->FileHeader.NumberOfSections;
|
Sections = NtHeaders->FileHeader.NumberOfSections;
|
||||||
Alignment = NtHeaders->OptionalHeader.SectionAlignment - 1;
|
Alignment = NtHeaders->OptionalHeader.SectionAlignment - 1;
|
||||||
|
|
||||||
/* Loop each section */
|
/* Loop each section */
|
||||||
Section = IMAGE_FIRST_SECTION(NtHeaders);
|
Section = IMAGE_FIRST_SECTION(NtHeaders);
|
||||||
while (Sections)
|
while (Sections)
|
||||||
|
@ -2357,10 +2356,10 @@ MiEnablePagingOfDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
|
||||||
Section->
|
Section->
|
||||||
VirtualAddress));
|
VirtualAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute the size */
|
/* Compute the size */
|
||||||
Size = max(Section->SizeOfRawData, Section->Misc.VirtualSize);
|
Size = max(Section->SizeOfRawData, Section->Misc.VirtualSize);
|
||||||
|
|
||||||
/* Find the last PTE that maps this section */
|
/* Find the last PTE that maps this section */
|
||||||
LastPte = MiAddressToPte(ImageBase +
|
LastPte = MiAddressToPte(ImageBase +
|
||||||
Section->VirtualAddress +
|
Section->VirtualAddress +
|
||||||
|
@ -2378,12 +2377,12 @@ MiEnablePagingOfDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
|
||||||
PointerPte = NULL;
|
PointerPte = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep searching */
|
/* Keep searching */
|
||||||
Sections--;
|
Sections--;
|
||||||
Section++;
|
Section++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle the straggler */
|
/* Handle the straggler */
|
||||||
if (PointerPte) MiSetPagingOfDriver(PointerPte, LastPte);
|
if (PointerPte) MiSetPagingOfDriver(PointerPte, LastPte);
|
||||||
}
|
}
|
||||||
|
@ -2427,7 +2426,7 @@ MmCheckSystemImage(IN HANDLE ImageHandle,
|
||||||
PIMAGE_NT_HEADERS NtHeaders;
|
PIMAGE_NT_HEADERS NtHeaders;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Setup the object attributes */
|
/* Setup the object attributes */
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -2485,7 +2484,7 @@ MmCheckSystemImage(IN HANDLE ImageHandle,
|
||||||
Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
|
Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
|
||||||
goto Fail;
|
goto Fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure it's a real image */
|
/* Make sure it's a real image */
|
||||||
NtHeaders = RtlImageNtHeader(ViewBase);
|
NtHeaders = RtlImageNtHeader(ViewBase);
|
||||||
if (!NtHeaders)
|
if (!NtHeaders)
|
||||||
|
@ -2494,7 +2493,7 @@ MmCheckSystemImage(IN HANDLE ImageHandle,
|
||||||
Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
|
Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
|
||||||
goto Fail;
|
goto Fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure it's for the correct architecture */
|
/* Make sure it's for the correct architecture */
|
||||||
if ((NtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_NATIVE) ||
|
if ((NtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_NATIVE) ||
|
||||||
(NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC))
|
(NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC))
|
||||||
|
@ -2606,7 +2605,7 @@ MmLoadSystemImage(IN PUNICODE_STRING FileName,
|
||||||
|
|
||||||
/* Check if we already have a name, use it instead */
|
/* Check if we already have a name, use it instead */
|
||||||
if (LoadedName) BaseName = *LoadedName;
|
if (LoadedName) BaseName = *LoadedName;
|
||||||
|
|
||||||
/* Check for loader snap debugging */
|
/* Check for loader snap debugging */
|
||||||
if (NtGlobalFlag & FLG_SHOW_LDR_SNAPS)
|
if (NtGlobalFlag & FLG_SHOW_LDR_SNAPS)
|
||||||
{
|
{
|
||||||
|
@ -2799,7 +2798,7 @@ LoaderScan:
|
||||||
ObDereferenceObject(Section);
|
ObDereferenceObject(Section);
|
||||||
Section = NULL;
|
Section = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for failure of the load earlier */
|
/* Check for failure of the load earlier */
|
||||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||||
|
|
||||||
|
@ -2812,7 +2811,7 @@ LoaderScan:
|
||||||
STATUS_INVALID_IMAGE_FORMAT);
|
STATUS_INVALID_IMAGE_FORMAT);
|
||||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||||
|
|
||||||
|
|
||||||
/* Get the NT Header */
|
/* Get the NT Header */
|
||||||
NtHeader = RtlImageNtHeader(ModuleLoadBase);
|
NtHeader = RtlImageNtHeader(ModuleLoadBase);
|
||||||
|
|
||||||
|
@ -3016,7 +3015,7 @@ MiLookupDataTableEntry(IN PVOID Address)
|
||||||
PLDR_DATA_TABLE_ENTRY LdrEntry, FoundEntry = NULL;
|
PLDR_DATA_TABLE_ENTRY LdrEntry, FoundEntry = NULL;
|
||||||
PLIST_ENTRY NextEntry;
|
PLIST_ENTRY NextEntry;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Loop entries */
|
/* Loop entries */
|
||||||
NextEntry = PsLoadedModuleList.Flink;
|
NextEntry = PsLoadedModuleList.Flink;
|
||||||
do
|
do
|
||||||
|
@ -3025,7 +3024,7 @@ MiLookupDataTableEntry(IN PVOID Address)
|
||||||
LdrEntry = CONTAINING_RECORD(NextEntry,
|
LdrEntry = CONTAINING_RECORD(NextEntry,
|
||||||
LDR_DATA_TABLE_ENTRY,
|
LDR_DATA_TABLE_ENTRY,
|
||||||
InLoadOrderLinks);
|
InLoadOrderLinks);
|
||||||
|
|
||||||
/* Check if the address matches */
|
/* Check if the address matches */
|
||||||
if ((Address >= LdrEntry->DllBase) &&
|
if ((Address >= LdrEntry->DllBase) &&
|
||||||
(Address < (PVOID)((ULONG_PTR)LdrEntry->DllBase +
|
(Address < (PVOID)((ULONG_PTR)LdrEntry->DllBase +
|
||||||
|
@ -3035,11 +3034,11 @@ MiLookupDataTableEntry(IN PVOID Address)
|
||||||
FoundEntry = LdrEntry;
|
FoundEntry = LdrEntry;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move on */
|
/* Move on */
|
||||||
NextEntry = NextEntry->Flink;
|
NextEntry = NextEntry->Flink;
|
||||||
} while(NextEntry != &PsLoadedModuleList);
|
} while(NextEntry != &PsLoadedModuleList);
|
||||||
|
|
||||||
/* Return the entry */
|
/* Return the entry */
|
||||||
return FoundEntry;
|
return FoundEntry;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::SYSPTE"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -36,22 +35,22 @@ MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PMMPTE PointerPte, NextPte, PreviousPte;
|
PMMPTE PointerPte, NextPte, PreviousPte;
|
||||||
ULONG_PTR ClusterSize;
|
ULONG_PTR ClusterSize;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity check
|
// Sanity check
|
||||||
//
|
//
|
||||||
ASSERT(Alignment <= PAGE_SIZE);
|
ASSERT(Alignment <= PAGE_SIZE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Lock the system PTE space
|
// Lock the system PTE space
|
||||||
//
|
//
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueSystemSpaceLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueueSystemSpaceLock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the first free cluster and make sure we have PTEs available
|
// Get the first free cluster and make sure we have PTEs available
|
||||||
//
|
//
|
||||||
PointerPte = &MmFirstFreeSystemPte[SystemPtePoolType];
|
PointerPte = &MmFirstFreeSystemPte[SystemPtePoolType];
|
||||||
if (PointerPte->u.List.NextEntry == ((ULONG)0xFFFFF))
|
if (PointerPte->u.List.NextEntry == ((ULONG)0xFFFFF))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Fail
|
// Fail
|
||||||
|
@ -59,13 +58,13 @@ MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
|
||||||
KeReleaseQueuedSpinLock(LockQueueSystemSpaceLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueueSystemSpaceLock, OldIrql);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now move to the first free system PTE cluster
|
// Now move to the first free system PTE cluster
|
||||||
//
|
//
|
||||||
PreviousPte = PointerPte;
|
PreviousPte = PointerPte;
|
||||||
PointerPte = MmSystemPteBase + PointerPte->u.List.NextEntry;
|
PointerPte = MmSystemPteBase + PointerPte->u.List.NextEntry;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop each cluster
|
// Loop each cluster
|
||||||
//
|
//
|
||||||
|
@ -80,7 +79,7 @@ MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
|
||||||
// Keep track of the next cluster in case we have to relink
|
// Keep track of the next cluster in case we have to relink
|
||||||
//
|
//
|
||||||
NextPte = PointerPte + 1;
|
NextPte = PointerPte + 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Can this cluster satisfy the request?
|
// Can this cluster satisfy the request?
|
||||||
//
|
//
|
||||||
|
@ -104,7 +103,7 @@ MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
|
||||||
//
|
//
|
||||||
NextPte->u.List.NextEntry = ClusterSize - NumberOfPtes;
|
NextPte->u.List.NextEntry = ClusterSize - NumberOfPtes;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Decrement the free count and move to the next starting PTE
|
// Decrement the free count and move to the next starting PTE
|
||||||
//
|
//
|
||||||
|
@ -112,7 +111,7 @@ MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
|
||||||
PointerPte += (ClusterSize - NumberOfPtes);
|
PointerPte += (ClusterSize - NumberOfPtes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Did we find exactly what you wanted?
|
// Did we find exactly what you wanted?
|
||||||
//
|
//
|
||||||
|
@ -124,7 +123,7 @@ MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
|
||||||
PreviousPte->u.List.NextEntry = PointerPte->u.List.NextEntry;
|
PreviousPte->u.List.NextEntry = PointerPte->u.List.NextEntry;
|
||||||
MmTotalFreeSystemPtes[SystemPtePoolType] -= NumberOfPtes;
|
MmTotalFreeSystemPtes[SystemPtePoolType] -= NumberOfPtes;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (NumberOfPtes == 1)
|
else if (NumberOfPtes == 1)
|
||||||
{
|
{
|
||||||
|
@ -135,7 +134,7 @@ MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
|
||||||
MmTotalFreeSystemPtes[SystemPtePoolType]--;
|
MmTotalFreeSystemPtes[SystemPtePoolType]--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// We couldn't find what you wanted -- is this the last cluster?
|
// We couldn't find what you wanted -- is this the last cluster?
|
||||||
//
|
//
|
||||||
|
@ -154,8 +153,8 @@ MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
|
||||||
PreviousPte = PointerPte;
|
PreviousPte = PointerPte;
|
||||||
PointerPte = MmSystemPteBase + PointerPte->u.List.NextEntry;
|
PointerPte = MmSystemPteBase + PointerPte->u.List.NextEntry;
|
||||||
ASSERT(PointerPte > PreviousPte);
|
ASSERT(PointerPte > PreviousPte);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the lock, flush the TLB and return the first PTE
|
// Release the lock, flush the TLB and return the first PTE
|
||||||
//
|
//
|
||||||
|
@ -202,30 +201,30 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte,
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
ULONG_PTR ClusterSize, CurrentSize;
|
ULONG_PTR ClusterSize, CurrentSize;
|
||||||
PMMPTE CurrentPte, NextPte, PointerPte;
|
PMMPTE CurrentPte, NextPte, PointerPte;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check to make sure the PTE address is within bounds
|
// Check to make sure the PTE address is within bounds
|
||||||
//
|
//
|
||||||
ASSERT(NumberOfPtes != 0);
|
ASSERT(NumberOfPtes != 0);
|
||||||
ASSERT(StartingPte >= MmSystemPtesStart[SystemPtePoolType]);
|
ASSERT(StartingPte >= MmSystemPtesStart[SystemPtePoolType]);
|
||||||
ASSERT(StartingPte <= MmSystemPtesEnd[SystemPtePoolType]);
|
ASSERT(StartingPte <= MmSystemPtesEnd[SystemPtePoolType]);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Zero PTEs
|
// Zero PTEs
|
||||||
//
|
//
|
||||||
RtlZeroMemory(StartingPte, NumberOfPtes * sizeof(MMPTE));
|
RtlZeroMemory(StartingPte, NumberOfPtes * sizeof(MMPTE));
|
||||||
CurrentSize = (ULONG_PTR)(StartingPte - MmSystemPteBase);
|
CurrentSize = (ULONG_PTR)(StartingPte - MmSystemPteBase);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Acquire the system PTE lock
|
// Acquire the system PTE lock
|
||||||
//
|
//
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueSystemSpaceLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueueSystemSpaceLock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Increase availability
|
// Increase availability
|
||||||
//
|
//
|
||||||
MmTotalFreeSystemPtes[SystemPtePoolType] += NumberOfPtes;
|
MmTotalFreeSystemPtes[SystemPtePoolType] += NumberOfPtes;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the free cluster and start going through them
|
// Get the free cluster and start going through them
|
||||||
//
|
//
|
||||||
|
@ -243,12 +242,12 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte,
|
||||||
//
|
//
|
||||||
ASSERT(((StartingPte + NumberOfPtes) <= PointerPte) ||
|
ASSERT(((StartingPte + NumberOfPtes) <= PointerPte) ||
|
||||||
(CurrentPte->u.List.NextEntry == ((ULONG)0xFFFFF)));
|
(CurrentPte->u.List.NextEntry == ((ULONG)0xFFFFF)));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the next cluster in case it's the one
|
// Get the next cluster in case it's the one
|
||||||
//
|
//
|
||||||
NextPte = CurrentPte + 1;
|
NextPte = CurrentPte + 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this was actually a single-PTE entry
|
// Check if this was actually a single-PTE entry
|
||||||
//
|
//
|
||||||
|
@ -266,7 +265,7 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte,
|
||||||
//
|
//
|
||||||
ClusterSize = (ULONG_PTR)NextPte->u.List.NextEntry;
|
ClusterSize = (ULONG_PTR)NextPte->u.List.NextEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// So check if this cluster actually describes the entire mapping
|
// So check if this cluster actually describes the entire mapping
|
||||||
//
|
//
|
||||||
|
@ -278,7 +277,7 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte,
|
||||||
NumberOfPtes += ClusterSize;
|
NumberOfPtes += ClusterSize;
|
||||||
NextPte->u.List.NextEntry = NumberOfPtes;
|
NextPte->u.List.NextEntry = NumberOfPtes;
|
||||||
CurrentPte->u.List.OneEntry = 0;
|
CurrentPte->u.List.OneEntry = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make another pass
|
// Make another pass
|
||||||
//
|
//
|
||||||
|
@ -291,7 +290,7 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte,
|
||||||
//
|
//
|
||||||
StartingPte->u.List.NextEntry = CurrentPte->u.List.NextEntry;
|
StartingPte->u.List.NextEntry = CurrentPte->u.List.NextEntry;
|
||||||
CurrentPte->u.List.NextEntry = CurrentSize;
|
CurrentPte->u.List.NextEntry = CurrentSize;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Is there just one page left?
|
// Is there just one page left?
|
||||||
//
|
//
|
||||||
|
@ -312,7 +311,7 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte,
|
||||||
NextPte->u.List.NextEntry = NumberOfPtes;
|
NextPte->u.List.NextEntry = NumberOfPtes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now check if we've arrived at yet another cluster
|
// Now check if we've arrived at yet another cluster
|
||||||
//
|
//
|
||||||
|
@ -324,7 +323,7 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte,
|
||||||
StartingPte->u.List.NextEntry = PointerPte->u.List.NextEntry;
|
StartingPte->u.List.NextEntry = PointerPte->u.List.NextEntry;
|
||||||
StartingPte->u.List.OneEntry = 0;
|
StartingPte->u.List.OneEntry = 0;
|
||||||
NextPte = StartingPte + 1;
|
NextPte = StartingPte + 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if the cluster only had one page
|
// Check if the cluster only had one page
|
||||||
//
|
//
|
||||||
|
@ -343,20 +342,20 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte,
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
ClusterSize = (ULONG_PTR)PointerPte->u.List.NextEntry;
|
ClusterSize = (ULONG_PTR)PointerPte->u.List.NextEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// And create the final combined cluster
|
// And create the final combined cluster
|
||||||
//
|
//
|
||||||
NextPte->u.List.NextEntry = NumberOfPtes + ClusterSize;
|
NextPte->u.List.NextEntry = NumberOfPtes + ClusterSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// We released the PTEs into their cluster (and optimized the list)
|
// We released the PTEs into their cluster (and optimized the list)
|
||||||
//
|
//
|
||||||
KeReleaseQueuedSpinLock(LockQueueSystemSpaceLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueueSystemSpaceLock, OldIrql);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Try the next cluster of PTEs...
|
// Try the next cluster of PTEs...
|
||||||
//
|
//
|
||||||
|
@ -375,7 +374,7 @@ MiInitializeSystemPtes(IN PMMPTE StartingPte,
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
//
|
//
|
||||||
ASSERT(NumberOfPtes >= 1);
|
ASSERT(NumberOfPtes >= 1);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set the starting and ending PTE addresses for this space
|
// Set the starting and ending PTE addresses for this space
|
||||||
//
|
//
|
||||||
|
@ -384,12 +383,12 @@ MiInitializeSystemPtes(IN PMMPTE StartingPte,
|
||||||
MmSystemPtesEnd[PoolType] = StartingPte + NumberOfPtes - 1;
|
MmSystemPtesEnd[PoolType] = StartingPte + NumberOfPtes - 1;
|
||||||
DPRINT("System PTE space for %d starting at: %p and ending at: %p\n",
|
DPRINT("System PTE space for %d starting at: %p and ending at: %p\n",
|
||||||
PoolType, MmSystemPtesStart[PoolType], MmSystemPtesEnd[PoolType]);
|
PoolType, MmSystemPtesStart[PoolType], MmSystemPtesEnd[PoolType]);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Clear all the PTEs to start with
|
// Clear all the PTEs to start with
|
||||||
//
|
//
|
||||||
RtlZeroMemory(StartingPte, NumberOfPtes * sizeof(MMPTE));
|
RtlZeroMemory(StartingPte, NumberOfPtes * sizeof(MMPTE));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make the first entry free and link it
|
// Make the first entry free and link it
|
||||||
//
|
//
|
||||||
|
@ -397,19 +396,19 @@ MiInitializeSystemPtes(IN PMMPTE StartingPte,
|
||||||
MmFirstFreeSystemPte[PoolType].u.Long = 0;
|
MmFirstFreeSystemPte[PoolType].u.Long = 0;
|
||||||
MmFirstFreeSystemPte[PoolType].u.List.NextEntry = StartingPte -
|
MmFirstFreeSystemPte[PoolType].u.List.NextEntry = StartingPte -
|
||||||
MmSystemPteBase;
|
MmSystemPteBase;
|
||||||
|
|
||||||
//
|
//
|
||||||
// The second entry stores the size of this PTE space
|
// The second entry stores the size of this PTE space
|
||||||
//
|
//
|
||||||
StartingPte++;
|
StartingPte++;
|
||||||
StartingPte->u.Long = 0;
|
StartingPte->u.Long = 0;
|
||||||
StartingPte->u.List.NextEntry = NumberOfPtes;
|
StartingPte->u.List.NextEntry = NumberOfPtes;
|
||||||
|
|
||||||
//
|
//
|
||||||
// We also keep a global for it
|
// We also keep a global for it
|
||||||
//
|
//
|
||||||
MmTotalFreeSystemPtes[PoolType] = NumberOfPtes;
|
MmTotalFreeSystemPtes[PoolType] = NumberOfPtes;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is the system PTE space
|
// Check if this is the system PTE space
|
||||||
//
|
//
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::VADNODE"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -86,7 +85,7 @@ MiCheckForConflictingNode(IN ULONG_PTR StartVpn,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return either the conflicting node, or no node at all */
|
/* Return either the conflicting node, or no node at all */
|
||||||
return CurrentNode;
|
return CurrentNode;
|
||||||
}
|
}
|
||||||
|
@ -147,16 +146,16 @@ MiInsertVad(IN PMMVAD Vad,
|
||||||
{
|
{
|
||||||
TABLE_SEARCH_RESULT Result;
|
TABLE_SEARCH_RESULT Result;
|
||||||
PMMADDRESS_NODE Parent = NULL;
|
PMMADDRESS_NODE Parent = NULL;
|
||||||
|
|
||||||
/* Validate the VAD and set it as the current hint */
|
/* Validate the VAD and set it as the current hint */
|
||||||
ASSERT(Vad->EndingVpn >= Vad->StartingVpn);
|
ASSERT(Vad->EndingVpn >= Vad->StartingVpn);
|
||||||
Process->VadRoot.NodeHint = Vad;
|
Process->VadRoot.NodeHint = Vad;
|
||||||
|
|
||||||
/* Find the parent VAD and where this child should be inserted */
|
/* Find the parent VAD and where this child should be inserted */
|
||||||
Result = RtlpFindAvlTableNodeOrParent(&Process->VadRoot, (PVOID)Vad->StartingVpn, &Parent);
|
Result = RtlpFindAvlTableNodeOrParent(&Process->VadRoot, (PVOID)Vad->StartingVpn, &Parent);
|
||||||
ASSERT(Result != TableFoundNode);
|
ASSERT(Result != TableFoundNode);
|
||||||
ASSERT((Parent != NULL) || (Result == TableEmptyTree));
|
ASSERT((Parent != NULL) || (Result == TableEmptyTree));
|
||||||
|
|
||||||
/* Do the actual insert operation */
|
/* Do the actual insert operation */
|
||||||
MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result);
|
MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result);
|
||||||
}
|
}
|
||||||
|
@ -168,7 +167,7 @@ MiRemoveNode(IN PMMADDRESS_NODE Node,
|
||||||
{
|
{
|
||||||
/* Call the AVL code */
|
/* Call the AVL code */
|
||||||
RtlpDeleteAvlTreeNode(Table, Node);
|
RtlpDeleteAvlTreeNode(Table, Node);
|
||||||
|
|
||||||
/* Decrease element count */
|
/* Decrease element count */
|
||||||
Table->NumberGenericTableElements--;
|
Table->NumberGenericTableElements--;
|
||||||
|
|
||||||
|
@ -186,7 +185,7 @@ MiRemoveNode(IN PMMADDRESS_NODE Node,
|
||||||
{
|
{
|
||||||
PMEMORY_AREA MemoryArea;
|
PMEMORY_AREA MemoryArea;
|
||||||
PEPROCESS Process;
|
PEPROCESS Process;
|
||||||
|
|
||||||
/* Check if this is VM VAD */
|
/* Check if this is VM VAD */
|
||||||
if (Vad->ControlArea == NULL)
|
if (Vad->ControlArea == NULL)
|
||||||
{
|
{
|
||||||
|
@ -198,17 +197,17 @@ MiRemoveNode(IN PMMADDRESS_NODE Node,
|
||||||
/* This is a section VAD. We store the ReactOS MEMORY_AREA here */
|
/* This is a section VAD. We store the ReactOS MEMORY_AREA here */
|
||||||
MemoryArea = (PMEMORY_AREA)Vad->ControlArea->WaitingForDeletion;
|
MemoryArea = (PMEMORY_AREA)Vad->ControlArea->WaitingForDeletion;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure one actually still exists */
|
/* Make sure one actually still exists */
|
||||||
if (MemoryArea)
|
if (MemoryArea)
|
||||||
{
|
{
|
||||||
/* Get the process */
|
/* Get the process */
|
||||||
Process = CONTAINING_RECORD(Table, EPROCESS, VadRoot);
|
Process = CONTAINING_RECORD(Table, EPROCESS, VadRoot);
|
||||||
|
|
||||||
/* We only create fake memory-areas for ARM3 VADs */
|
/* We only create fake memory-areas for ARM3 VADs */
|
||||||
ASSERT(MemoryArea->Type == MEMORY_AREA_OWNED_BY_ARM3);
|
ASSERT(MemoryArea->Type == MEMORY_AREA_OWNED_BY_ARM3);
|
||||||
ASSERT(MemoryArea->Vad == NULL);
|
ASSERT(MemoryArea->Vad == NULL);
|
||||||
|
|
||||||
/* Free it */
|
/* Free it */
|
||||||
MmFreeMemoryArea(&Process->Vm, MemoryArea, NULL, NULL);
|
MmFreeMemoryArea(&Process->Vm, MemoryArea, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
@ -241,12 +240,12 @@ MiGetPreviousNode(IN PMMADDRESS_NODE Node)
|
||||||
if (Parent == RtlParentAvl(Parent)) Parent = NULL;
|
if (Parent == RtlParentAvl(Parent)) Parent = NULL;
|
||||||
return Parent;
|
return Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep lopping until we find our parent */
|
/* Keep lopping until we find our parent */
|
||||||
Node = Parent;
|
Node = Parent;
|
||||||
Parent = RtlParentAvl(Node);
|
Parent = RtlParentAvl(Node);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nothing found */
|
/* Nothing found */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -276,12 +275,12 @@ MiGetNextNode(IN PMMADDRESS_NODE Node)
|
||||||
/* Return it */
|
/* Return it */
|
||||||
return Parent;
|
return Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep lopping until we find our parent */
|
/* Keep lopping until we find our parent */
|
||||||
Node = Parent;
|
Node = Parent;
|
||||||
Parent = RtlParentAvl(Node);
|
Parent = RtlParentAvl(Node);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nothing found */
|
/* Nothing found */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -328,7 +327,7 @@ FoundAtBottom:
|
||||||
{
|
{
|
||||||
/* The last aligned page number in this entry */
|
/* The last aligned page number in this entry */
|
||||||
LowVpn = ROUND_UP(Node->EndingVpn + 1, AlignmentVpn);
|
LowVpn = ROUND_UP(Node->EndingVpn + 1, AlignmentVpn);
|
||||||
|
|
||||||
/* Keep going as long as there's still a next node */
|
/* Keep going as long as there's still a next node */
|
||||||
NextNode = MiGetNextNode(Node);
|
NextNode = MiGetNextNode(Node);
|
||||||
if (!NextNode) break;
|
if (!NextNode) break;
|
||||||
|
@ -340,7 +339,7 @@ FoundAtBottom:
|
||||||
Found:
|
Found:
|
||||||
/* Yes! Use this VAD to store the allocation */
|
/* Yes! Use this VAD to store the allocation */
|
||||||
*PreviousVad = Node;
|
*PreviousVad = Node;
|
||||||
*Base = ROUND_UP((Node->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
|
*Base = ROUND_UP((Node->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
|
||||||
Alignment);
|
Alignment);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -352,7 +351,7 @@ Found:
|
||||||
/* We're down to the last (top) VAD, will this allocation fit inside it? */
|
/* We're down to the last (top) VAD, will this allocation fit inside it? */
|
||||||
HighestVpn = ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1) >> PAGE_SHIFT;
|
HighestVpn = ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1) >> PAGE_SHIFT;
|
||||||
if ((HighestVpn > LowVpn) && (LengthVpn <= HighestVpn - LowVpn)) goto Found;
|
if ((HighestVpn > LowVpn) && (LengthVpn <= HighestVpn - LowVpn)) goto Found;
|
||||||
|
|
||||||
/* Nyet, there's no free address space for this allocation, so we'll fail */
|
/* Nyet, there's no free address space for this allocation, so we'll fail */
|
||||||
return STATUS_NO_MEMORY;
|
return STATUS_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -373,7 +372,7 @@ MiFindEmptyAddressRangeDownTree(IN SIZE_T Length,
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
ASSERT(BoundaryAddress);
|
ASSERT(BoundaryAddress);
|
||||||
ASSERT(BoundaryAddress <= ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
|
ASSERT(BoundaryAddress <= ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
|
||||||
|
|
||||||
/* Compute page length, make sure the boundary address is valid */
|
/* Compute page length, make sure the boundary address is valid */
|
||||||
Length = ROUND_TO_PAGES(Length);
|
Length = ROUND_TO_PAGES(Length);
|
||||||
PageCount = Length >> PAGE_SHIFT;
|
PageCount = Length >> PAGE_SHIFT;
|
||||||
|
@ -390,10 +389,10 @@ MiFindEmptyAddressRangeDownTree(IN SIZE_T Length,
|
||||||
/* Calculate the initial upper margin */
|
/* Calculate the initial upper margin */
|
||||||
HighVpn = BoundaryAddress >> PAGE_SHIFT;
|
HighVpn = BoundaryAddress >> PAGE_SHIFT;
|
||||||
|
|
||||||
/* Starting from the root, go down until the right-most child,
|
/* Starting from the root, go down until the right-most child,
|
||||||
trying to stay below the boundary. */
|
trying to stay below the boundary. */
|
||||||
LowestNode = Node = RtlRightChildAvl(&Table->BalancedRoot);
|
LowestNode = Node = RtlRightChildAvl(&Table->BalancedRoot);
|
||||||
while ( (Child = RtlRightChildAvl(Node)) &&
|
while ( (Child = RtlRightChildAvl(Node)) &&
|
||||||
Child->EndingVpn < HighVpn ) Node = Child;
|
Child->EndingVpn < HighVpn ) Node = Child;
|
||||||
|
|
||||||
/* Now loop the Vad nodes */
|
/* Now loop the Vad nodes */
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::VIRTUAL"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -41,7 +40,7 @@ MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress,
|
||||||
ASSERT(PageTableVirtualAddress > MM_HIGHEST_USER_ADDRESS);
|
ASSERT(PageTableVirtualAddress > MM_HIGHEST_USER_ADDRESS);
|
||||||
ASSERT((PageTableVirtualAddress < MmPagedPoolStart) ||
|
ASSERT((PageTableVirtualAddress < MmPagedPoolStart) ||
|
||||||
(PageTableVirtualAddress > MmPagedPoolEnd));
|
(PageTableVirtualAddress > MmPagedPoolEnd));
|
||||||
|
|
||||||
/* Working set lock or PFN lock should be held */
|
/* Working set lock or PFN lock should be held */
|
||||||
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
||||||
|
|
||||||
|
@ -84,7 +83,7 @@ MiMakeSystemAddressValidPfn(IN PVOID VirtualAddress,
|
||||||
{
|
{
|
||||||
/* Release the PFN database */
|
/* Release the PFN database */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
/* Fault it in */
|
/* Fault it in */
|
||||||
Status = MmAccessFault(FALSE, VirtualAddress, KernelMode, NULL);
|
Status = MmAccessFault(FALSE, VirtualAddress, KernelMode, NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
@ -99,7 +98,7 @@ MiMakeSystemAddressValidPfn(IN PVOID VirtualAddress,
|
||||||
|
|
||||||
/* This flag will be useful later when we do better locking */
|
/* This flag will be useful later when we do better locking */
|
||||||
LockChange = TRUE;
|
LockChange = TRUE;
|
||||||
|
|
||||||
/* Lock the PFN database */
|
/* Lock the PFN database */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
}
|
}
|
||||||
|
@ -114,17 +113,17 @@ MiDeleteSystemPageableVm(IN PMMPTE PointerPte,
|
||||||
IN PFN_NUMBER PageCount,
|
IN PFN_NUMBER PageCount,
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
OUT PPFN_NUMBER ValidPages)
|
OUT PPFN_NUMBER ValidPages)
|
||||||
{
|
{
|
||||||
PFN_NUMBER ActualPages = 0;
|
PFN_NUMBER ActualPages = 0;
|
||||||
PETHREAD CurrentThread = PsGetCurrentThread();
|
PETHREAD CurrentThread = PsGetCurrentThread();
|
||||||
PMMPFN Pfn1, Pfn2;
|
PMMPFN Pfn1, Pfn2;
|
||||||
PFN_NUMBER PageFrameIndex, PageTableIndex;
|
PFN_NUMBER PageFrameIndex, PageTableIndex;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||||
|
|
||||||
/* Lock the system working set */
|
/* Lock the system working set */
|
||||||
MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
|
MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
|
||||||
|
|
||||||
/* Loop all pages */
|
/* Loop all pages */
|
||||||
while (PageCount)
|
while (PageCount)
|
||||||
{
|
{
|
||||||
|
@ -134,50 +133,50 @@ MiDeleteSystemPageableVm(IN PMMPTE PointerPte,
|
||||||
/* As always, only handle current ARM3 scenarios */
|
/* As always, only handle current ARM3 scenarios */
|
||||||
ASSERT(PointerPte->u.Soft.Prototype == 0);
|
ASSERT(PointerPte->u.Soft.Prototype == 0);
|
||||||
ASSERT(PointerPte->u.Soft.Transition == 0);
|
ASSERT(PointerPte->u.Soft.Transition == 0);
|
||||||
|
|
||||||
/* Normally this is one possibility -- freeing a valid page */
|
/* Normally this is one possibility -- freeing a valid page */
|
||||||
if (PointerPte->u.Hard.Valid)
|
if (PointerPte->u.Hard.Valid)
|
||||||
{
|
{
|
||||||
/* Get the page PFN */
|
/* Get the page PFN */
|
||||||
PageFrameIndex = PFN_FROM_PTE(PointerPte);
|
PageFrameIndex = PFN_FROM_PTE(PointerPte);
|
||||||
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
||||||
|
|
||||||
/* Should not have any working set data yet */
|
/* Should not have any working set data yet */
|
||||||
ASSERT(Pfn1->u1.WsIndex == 0);
|
ASSERT(Pfn1->u1.WsIndex == 0);
|
||||||
|
|
||||||
/* Actual valid, legitimate, pages */
|
/* Actual valid, legitimate, pages */
|
||||||
if (ValidPages) (*ValidPages)++;
|
if (ValidPages) (*ValidPages)++;
|
||||||
|
|
||||||
/* Get the page table entry */
|
/* Get the page table entry */
|
||||||
PageTableIndex = Pfn1->u4.PteFrame;
|
PageTableIndex = Pfn1->u4.PteFrame;
|
||||||
Pfn2 = MiGetPfnEntry(PageTableIndex);
|
Pfn2 = MiGetPfnEntry(PageTableIndex);
|
||||||
|
|
||||||
/* Lock the PFN database */
|
/* Lock the PFN database */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
/* Delete it the page */
|
/* Delete it the page */
|
||||||
MI_SET_PFN_DELETED(Pfn1);
|
MI_SET_PFN_DELETED(Pfn1);
|
||||||
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
||||||
|
|
||||||
/* Decrement the page table too */
|
/* Decrement the page table too */
|
||||||
DPRINT("FIXME: ARM3 should decrement the pool PDE refcount for: %p\n", PageTableIndex);
|
DPRINT("FIXME: ARM3 should decrement the pool PDE refcount for: %p\n", PageTableIndex);
|
||||||
#if 0 // ARM3: Dont't trust this yet
|
#if 0 // ARM3: Dont't trust this yet
|
||||||
MiDecrementShareCount(Pfn2, PageTableIndex);
|
MiDecrementShareCount(Pfn2, PageTableIndex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Release the PFN database */
|
/* Release the PFN database */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
/* Destroy the PTE */
|
/* Destroy the PTE */
|
||||||
PointerPte->u.Long = 0;
|
PointerPte->u.Long = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Actual legitimate pages */
|
/* Actual legitimate pages */
|
||||||
ActualPages++;
|
ActualPages++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The only other ARM3 possibility is a demand zero page, which would
|
* The only other ARM3 possibility is a demand zero page, which would
|
||||||
* mean freeing some of the paged pool pages that haven't even been
|
* mean freeing some of the paged pool pages that haven't even been
|
||||||
* touched yet, as part of a larger allocation.
|
* touched yet, as part of a larger allocation.
|
||||||
|
@ -185,22 +184,22 @@ MiDeleteSystemPageableVm(IN PMMPTE PointerPte,
|
||||||
* Right now, we shouldn't expect any page file information in the PTE
|
* Right now, we shouldn't expect any page file information in the PTE
|
||||||
*/
|
*/
|
||||||
ASSERT(PointerPte->u.Soft.PageFileHigh == 0);
|
ASSERT(PointerPte->u.Soft.PageFileHigh == 0);
|
||||||
|
|
||||||
/* Destroy the PTE */
|
/* Destroy the PTE */
|
||||||
PointerPte->u.Long = 0;
|
PointerPte->u.Long = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep going */
|
/* Keep going */
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
PageCount--;
|
PageCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the working set */
|
/* Release the working set */
|
||||||
MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
|
MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
|
||||||
|
|
||||||
/* Flush the entire TLB */
|
/* Flush the entire TLB */
|
||||||
KeFlushEntireTb(TRUE, TRUE);
|
KeFlushEntireTb(TRUE, TRUE);
|
||||||
|
|
||||||
/* Done */
|
/* Done */
|
||||||
return ActualPages;
|
return ActualPages;
|
||||||
}
|
}
|
||||||
|
@ -243,7 +242,7 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
PointerPde = MiAddressToPde(PointerPte);
|
PointerPde = MiAddressToPde(PointerPte);
|
||||||
if (PointerPde->u.Hard.Valid == 0)
|
if (PointerPde->u.Hard.Valid == 0)
|
||||||
{
|
{
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
#if (_MI_PAGING_LEVELS == 2)
|
||||||
/* Could be paged pool access from a new process -- synchronize the page directories */
|
/* Could be paged pool access from a new process -- synchronize the page directories */
|
||||||
if (!NT_SUCCESS(MiCheckPdeForPagedPool(VirtualAddress)))
|
if (!NT_SUCCESS(MiCheckPdeForPagedPool(VirtualAddress)))
|
||||||
{
|
{
|
||||||
|
@ -255,7 +254,7 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
PointerPte->u.Long,
|
PointerPte->u.Long,
|
||||||
(ULONG_PTR)VirtualAddress);
|
(ULONG_PTR)VirtualAddress);
|
||||||
}
|
}
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
#if (_MI_PAGING_LEVELS == 2)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* FIXME: Drop the reference on the page table. For now, leak it until RosMM is gone */
|
/* FIXME: Drop the reference on the page table. For now, leak it until RosMM is gone */
|
||||||
|
@ -263,7 +262,7 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
|
|
||||||
/* Drop the share count */
|
/* Drop the share count */
|
||||||
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
||||||
|
|
||||||
/* No fork yet */
|
/* No fork yet */
|
||||||
if (PointerPte <= MiHighestUserPte) ASSERT(PrototypePte == Pfn1->PteAddress);
|
if (PointerPte <= MiHighestUserPte) ASSERT(PrototypePte == Pfn1->PteAddress);
|
||||||
}
|
}
|
||||||
|
@ -274,7 +273,7 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
{
|
{
|
||||||
/* The PFN entry is illegal, or invalid */
|
/* The PFN entry is illegal, or invalid */
|
||||||
KeBugCheckEx(MEMORY_MANAGEMENT,
|
KeBugCheckEx(MEMORY_MANAGEMENT,
|
||||||
0x401,
|
0x401,
|
||||||
(ULONG_PTR)PointerPte,
|
(ULONG_PTR)PointerPte,
|
||||||
PointerPte->u.Long,
|
PointerPte->u.Long,
|
||||||
(ULONG_PTR)Pfn1->PteAddress);
|
(ULONG_PTR)Pfn1->PteAddress);
|
||||||
|
@ -282,14 +281,14 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
|
|
||||||
/* There should only be 1 shared reference count */
|
/* There should only be 1 shared reference count */
|
||||||
ASSERT(Pfn1->u2.ShareCount == 1);
|
ASSERT(Pfn1->u2.ShareCount == 1);
|
||||||
|
|
||||||
/* FIXME: Drop the reference on the page table. For now, leak it until RosMM is gone */
|
/* FIXME: Drop the reference on the page table. For now, leak it until RosMM is gone */
|
||||||
//MiDecrementShareCount(MiGetPfnEntry(Pfn1->u4.PteFrame), Pfn1->u4.PteFrame);
|
//MiDecrementShareCount(MiGetPfnEntry(Pfn1->u4.PteFrame), Pfn1->u4.PteFrame);
|
||||||
|
|
||||||
/* Mark the PFN for deletion and dereference what should be the last ref */
|
/* Mark the PFN for deletion and dereference what should be the last ref */
|
||||||
MI_SET_PFN_DELETED(Pfn1);
|
MI_SET_PFN_DELETED(Pfn1);
|
||||||
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
||||||
|
|
||||||
/* We should eventually do this */
|
/* We should eventually do this */
|
||||||
//CurrentProcess->NumberOfPrivatePages--;
|
//CurrentProcess->NumberOfPrivatePages--;
|
||||||
}
|
}
|
||||||
|
@ -348,15 +347,15 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
||||||
|
|
||||||
/* Still no valid PDE, try the next 4MB (or whatever) */
|
/* Still no valid PDE, try the next 4MB (or whatever) */
|
||||||
PointerPde++;
|
PointerPde++;
|
||||||
|
|
||||||
/* Update the PTE on this new boundary */
|
/* Update the PTE on this new boundary */
|
||||||
PointerPte = MiPteToAddress(PointerPde);
|
PointerPte = MiPteToAddress(PointerPde);
|
||||||
|
|
||||||
/* Check if all the PDEs are invalid, so there's nothing to free */
|
/* Check if all the PDEs are invalid, so there's nothing to free */
|
||||||
Va = (ULONG_PTR)MiPteToAddress(PointerPte);
|
Va = (ULONG_PTR)MiPteToAddress(PointerPte);
|
||||||
if (Va > EndingAddress) return;
|
if (Va > EndingAddress) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now check if the PDE is mapped in */
|
/* Now check if the PDE is mapped in */
|
||||||
if (!PointerPde->u.Hard.Valid)
|
if (!PointerPde->u.Hard.Valid)
|
||||||
{
|
{
|
||||||
|
@ -364,17 +363,17 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
||||||
PointerPte = MiPteToAddress(PointerPde);
|
PointerPte = MiPteToAddress(PointerPde);
|
||||||
MiMakeSystemAddressValid(PointerPte, CurrentProcess);
|
MiMakeSystemAddressValid(PointerPte, CurrentProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we should have a valid PDE, mapped in, and still have some VA */
|
/* Now we should have a valid PDE, mapped in, and still have some VA */
|
||||||
ASSERT(PointerPde->u.Hard.Valid == 1);
|
ASSERT(PointerPde->u.Hard.Valid == 1);
|
||||||
ASSERT(Va <= EndingAddress);
|
ASSERT(Va <= EndingAddress);
|
||||||
|
|
||||||
/* Check if this is a section VAD with gaps in it */
|
/* Check if this is a section VAD with gaps in it */
|
||||||
if ((AddressGap) && (LastPrototypePte))
|
if ((AddressGap) && (LastPrototypePte))
|
||||||
{
|
{
|
||||||
/* We need to skip to the next correct prototype PTE */
|
/* We need to skip to the next correct prototype PTE */
|
||||||
PrototypePte = MI_GET_PROTOTYPE_PTE_FOR_VPN(Vad, Va >> PAGE_SHIFT);
|
PrototypePte = MI_GET_PROTOTYPE_PTE_FOR_VPN(Vad, Va >> PAGE_SHIFT);
|
||||||
|
|
||||||
/* And we need the subsection to skip to the next last prototype PTE */
|
/* And we need the subsection to skip to the next last prototype PTE */
|
||||||
Subsection = MiLocateSubsection(Vad, Va >> PAGE_SHIFT);
|
Subsection = MiLocateSubsection(Vad, Va >> PAGE_SHIFT);
|
||||||
if (Subsection)
|
if (Subsection)
|
||||||
|
@ -388,7 +387,7 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
||||||
PrototypePte = NULL;
|
PrototypePte = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the PFN Database while we delete the PTEs */
|
/* Lock the PFN Database while we delete the PTEs */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
do
|
do
|
||||||
|
@ -405,7 +404,7 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
||||||
{
|
{
|
||||||
/* We need to skip to the next correct prototype PTE */
|
/* We need to skip to the next correct prototype PTE */
|
||||||
PrototypePte = MI_GET_PROTOTYPE_PTE_FOR_VPN(Vad, Va >> PAGE_SHIFT);
|
PrototypePte = MI_GET_PROTOTYPE_PTE_FOR_VPN(Vad, Va >> PAGE_SHIFT);
|
||||||
|
|
||||||
/* And we need the subsection to skip to the next last prototype PTE */
|
/* And we need the subsection to skip to the next last prototype PTE */
|
||||||
Subsection = MiLocateSubsection(Vad, Va >> PAGE_SHIFT);
|
Subsection = MiLocateSubsection(Vad, Va >> PAGE_SHIFT);
|
||||||
if (Subsection)
|
if (Subsection)
|
||||||
|
@ -419,7 +418,7 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
||||||
PrototypePte = NULL;
|
PrototypePte = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for prototype PTE */
|
/* Check for prototype PTE */
|
||||||
if ((TempPte.u.Hard.Valid == 0) &&
|
if ((TempPte.u.Hard.Valid == 0) &&
|
||||||
(TempPte.u.Soft.Prototype == 1))
|
(TempPte.u.Soft.Prototype == 1))
|
||||||
|
@ -431,7 +430,7 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
||||||
{
|
{
|
||||||
/* Delete the PTE proper */
|
/* Delete the PTE proper */
|
||||||
MiDeletePte(PointerPte,
|
MiDeletePte(PointerPte,
|
||||||
(PVOID)Va,
|
(PVOID)Va,
|
||||||
CurrentProcess,
|
CurrentProcess,
|
||||||
PrototypePte);
|
PrototypePte);
|
||||||
}
|
}
|
||||||
|
@ -447,15 +446,15 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
||||||
Va += PAGE_SIZE;
|
Va += PAGE_SIZE;
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
PrototypePte++;
|
PrototypePte++;
|
||||||
|
|
||||||
/* Making sure the PDE is still valid */
|
/* Making sure the PDE is still valid */
|
||||||
ASSERT(PointerPde->u.Hard.Valid == 1);
|
ASSERT(PointerPde->u.Hard.Valid == 1);
|
||||||
}
|
}
|
||||||
while ((Va & (PDE_MAPPED_VA - 1)) && (Va <= EndingAddress));
|
while ((Va & (PDE_MAPPED_VA - 1)) && (Va <= EndingAddress));
|
||||||
|
|
||||||
/* The PDE should still be valid at this point */
|
/* The PDE should still be valid at this point */
|
||||||
ASSERT(PointerPde->u.Hard.Valid == 1);
|
ASSERT(PointerPde->u.Hard.Valid == 1);
|
||||||
|
|
||||||
/* Release the lock and get out if we're done */
|
/* Release the lock and get out if we're done */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
if (Va > EndingAddress) return;
|
if (Va > EndingAddress) return;
|
||||||
|
@ -468,7 +467,7 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
||||||
|
|
||||||
LONG
|
LONG
|
||||||
MiGetExceptionInfo(IN PEXCEPTION_POINTERS ExceptionInfo,
|
MiGetExceptionInfo(IN PEXCEPTION_POINTERS ExceptionInfo,
|
||||||
OUT PBOOLEAN HaveBadAddress,
|
OUT PBOOLEAN HaveBadAddress,
|
||||||
OUT PULONG_PTR BadAddress)
|
OUT PULONG_PTR BadAddress)
|
||||||
{
|
{
|
||||||
PEXCEPTION_RECORD ExceptionRecord;
|
PEXCEPTION_RECORD ExceptionRecord;
|
||||||
|
@ -666,7 +665,7 @@ MiDoMappedCopy(IN PEPROCESS SourceProcess,
|
||||||
// Check if we had locked the pages
|
// Check if we had locked the pages
|
||||||
//
|
//
|
||||||
if (PagesLocked) MmUnlockPages(Mdl);
|
if (PagesLocked) MmUnlockPages(Mdl);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we hit working set quota
|
// Check if we hit working set quota
|
||||||
//
|
//
|
||||||
|
@ -1032,7 +1031,7 @@ MmCopyVirtualMemory(IN PEPROCESS SourceProcess,
|
||||||
ExReleaseRundownProtection(&Process->RundownProtect);
|
ExReleaseRundownProtection(&Process->RundownProtect);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MmFlushVirtualMemory(IN PEPROCESS Process,
|
MmFlushVirtualMemory(IN PEPROCESS Process,
|
||||||
|
@ -1042,7 +1041,7 @@ MmFlushVirtualMemory(IN PEPROCESS Process,
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Fake success
|
// Fake success
|
||||||
//
|
//
|
||||||
|
@ -1110,7 +1109,7 @@ MiQueryAddressState(IN PVOID Va,
|
||||||
|
|
||||||
/* Only normal VADs supported */
|
/* Only normal VADs supported */
|
||||||
ASSERT(Vad->u.VadFlags.VadType == VadNone);
|
ASSERT(Vad->u.VadFlags.VadType == VadNone);
|
||||||
|
|
||||||
/* Get the PDE and PTE for the address */
|
/* Get the PDE and PTE for the address */
|
||||||
PointerPde = MiAddressToPde(Va);
|
PointerPde = MiAddressToPde(Va);
|
||||||
PointerPte = MiAddressToPte(Va);
|
PointerPte = MiAddressToPte(Va);
|
||||||
|
@ -1148,7 +1147,7 @@ MiQueryAddressState(IN PVOID Va,
|
||||||
if (ValidPte)
|
if (ValidPte)
|
||||||
{
|
{
|
||||||
/* FIXME: watch out for large pages */
|
/* FIXME: watch out for large pages */
|
||||||
|
|
||||||
/* Capture the PTE */
|
/* Capture the PTE */
|
||||||
TempPte = *PointerPte;
|
TempPte = *PointerPte;
|
||||||
if (TempPte.u.Long)
|
if (TempPte.u.Long)
|
||||||
|
@ -1184,7 +1183,7 @@ MiQueryAddressState(IN PVOID Va,
|
||||||
{
|
{
|
||||||
/* This is committed memory */
|
/* This is committed memory */
|
||||||
State = MEM_COMMIT;
|
State = MEM_COMMIT;
|
||||||
|
|
||||||
/* Convert the protection */
|
/* Convert the protection */
|
||||||
Protect = MmProtectToValue[Vad->u.VadFlags.Protection];
|
Protect = MmProtectToValue[Vad->u.VadFlags.Protection];
|
||||||
}
|
}
|
||||||
|
@ -1285,7 +1284,7 @@ NtReadVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Don't do zero-byte transfers
|
// Don't do zero-byte transfers
|
||||||
//
|
//
|
||||||
|
@ -1312,7 +1311,7 @@ NtReadVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
NumberOfBytesToRead,
|
NumberOfBytesToRead,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
&BytesRead);
|
&BytesRead);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Dereference the process
|
// Dereference the process
|
||||||
//
|
//
|
||||||
|
@ -1426,7 +1425,7 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
NumberOfBytesToWrite,
|
NumberOfBytesToWrite,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
&BytesWritten);
|
&BytesWritten);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Dereference the process
|
// Dereference the process
|
||||||
//
|
//
|
||||||
|
@ -1572,7 +1571,7 @@ NtProtectVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
(PVOID*)(&Process),
|
(PVOID*)(&Process),
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we should attach
|
// Check if we should attach
|
||||||
//
|
//
|
||||||
|
@ -1593,7 +1592,7 @@ NtProtectVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
&NumberOfBytesToProtect,
|
&NumberOfBytesToProtect,
|
||||||
NewAccessProtection,
|
NewAccessProtection,
|
||||||
&OldAccessProtection);
|
&OldAccessProtection);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Detach if needed
|
// Detach if needed
|
||||||
//
|
//
|
||||||
|
@ -1643,7 +1642,7 @@ NtLockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
PVOID CapturedBaseAddress;
|
PVOID CapturedBaseAddress;
|
||||||
SIZE_T CapturedBytesToLock;
|
SIZE_T CapturedBytesToLock;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Validate flags
|
// Validate flags
|
||||||
//
|
//
|
||||||
|
@ -1654,7 +1653,7 @@ NtLockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// At least one flag must be specified
|
// At least one flag must be specified
|
||||||
//
|
//
|
||||||
|
@ -1665,7 +1664,7 @@ NtLockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Enter SEH for probing
|
// Enter SEH for probing
|
||||||
//
|
//
|
||||||
|
@ -1676,7 +1675,7 @@ NtLockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
ProbeForWritePointer(BaseAddress);
|
ProbeForWritePointer(BaseAddress);
|
||||||
ProbeForWriteSize_t(NumberOfBytesToLock);
|
ProbeForWriteSize_t(NumberOfBytesToLock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Capture it
|
// Capture it
|
||||||
//
|
//
|
||||||
|
@ -1691,12 +1690,12 @@ NtLockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Catch illegal base address
|
// Catch illegal base address
|
||||||
//
|
//
|
||||||
if (CapturedBaseAddress > MM_HIGHEST_USER_ADDRESS) return STATUS_INVALID_PARAMETER;
|
if (CapturedBaseAddress > MM_HIGHEST_USER_ADDRESS) return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Catch illegal region size
|
// Catch illegal region size
|
||||||
//
|
//
|
||||||
|
@ -1707,12 +1706,12 @@ NtLockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// 0 is also illegal
|
// 0 is also illegal
|
||||||
//
|
//
|
||||||
if (!CapturedBytesToLock) return STATUS_INVALID_PARAMETER;
|
if (!CapturedBytesToLock) return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get a reference to the process
|
// Get a reference to the process
|
||||||
//
|
//
|
||||||
|
@ -1723,7 +1722,7 @@ NtLockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
(PVOID*)(&Process),
|
(PVOID*)(&Process),
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is is system-mapped
|
// Check if this is is system-mapped
|
||||||
//
|
//
|
||||||
|
@ -1741,7 +1740,7 @@ NtLockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
return STATUS_PRIVILEGE_NOT_HELD;
|
return STATUS_PRIVILEGE_NOT_HELD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we should attach
|
// Check if we should attach
|
||||||
//
|
//
|
||||||
|
@ -1753,22 +1752,22 @@ NtLockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
KeStackAttachProcess(&Process->Pcb, &ApcState);
|
KeStackAttachProcess(&Process->Pcb, &ApcState);
|
||||||
Attached = TRUE;
|
Attached = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Oops :(
|
// Oops :(
|
||||||
//
|
//
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Detach if needed
|
// Detach if needed
|
||||||
//
|
//
|
||||||
if (Attached) KeUnstackDetachProcess(&ApcState);
|
if (Attached) KeUnstackDetachProcess(&ApcState);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release reference
|
// Release reference
|
||||||
//
|
//
|
||||||
ObDereferenceObject(Process);
|
ObDereferenceObject(Process);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Enter SEH to return data
|
// Enter SEH to return data
|
||||||
//
|
//
|
||||||
|
@ -1788,7 +1787,7 @@ NtLockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return status
|
// Return status
|
||||||
//
|
//
|
||||||
|
@ -1811,7 +1810,7 @@ NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
PVOID CapturedBaseAddress;
|
PVOID CapturedBaseAddress;
|
||||||
SIZE_T CapturedBytesToUnlock;
|
SIZE_T CapturedBytesToUnlock;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Validate flags
|
// Validate flags
|
||||||
//
|
//
|
||||||
|
@ -1822,7 +1821,7 @@ NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// At least one flag must be specified
|
// At least one flag must be specified
|
||||||
//
|
//
|
||||||
|
@ -1833,7 +1832,7 @@ NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Enter SEH for probing
|
// Enter SEH for probing
|
||||||
//
|
//
|
||||||
|
@ -1844,7 +1843,7 @@ NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
ProbeForWritePointer(BaseAddress);
|
ProbeForWritePointer(BaseAddress);
|
||||||
ProbeForWriteSize_t(NumberOfBytesToUnlock);
|
ProbeForWriteSize_t(NumberOfBytesToUnlock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Capture it
|
// Capture it
|
||||||
//
|
//
|
||||||
|
@ -1859,12 +1858,12 @@ NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Catch illegal base address
|
// Catch illegal base address
|
||||||
//
|
//
|
||||||
if (CapturedBaseAddress > MM_HIGHEST_USER_ADDRESS) return STATUS_INVALID_PARAMETER;
|
if (CapturedBaseAddress > MM_HIGHEST_USER_ADDRESS) return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Catch illegal region size
|
// Catch illegal region size
|
||||||
//
|
//
|
||||||
|
@ -1875,12 +1874,12 @@ NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// 0 is also illegal
|
// 0 is also illegal
|
||||||
//
|
//
|
||||||
if (!CapturedBytesToUnlock) return STATUS_INVALID_PARAMETER;
|
if (!CapturedBytesToUnlock) return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get a reference to the process
|
// Get a reference to the process
|
||||||
//
|
//
|
||||||
|
@ -1891,7 +1890,7 @@ NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
(PVOID*)(&Process),
|
(PVOID*)(&Process),
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is is system-mapped
|
// Check if this is is system-mapped
|
||||||
//
|
//
|
||||||
|
@ -1909,7 +1908,7 @@ NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
return STATUS_PRIVILEGE_NOT_HELD;
|
return STATUS_PRIVILEGE_NOT_HELD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we should attach
|
// Check if we should attach
|
||||||
//
|
//
|
||||||
|
@ -1921,22 +1920,22 @@ NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
KeStackAttachProcess(&Process->Pcb, &ApcState);
|
KeStackAttachProcess(&Process->Pcb, &ApcState);
|
||||||
Attached = TRUE;
|
Attached = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Oops :(
|
// Oops :(
|
||||||
//
|
//
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Detach if needed
|
// Detach if needed
|
||||||
//
|
//
|
||||||
if (Attached) KeUnstackDetachProcess(&ApcState);
|
if (Attached) KeUnstackDetachProcess(&ApcState);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release reference
|
// Release reference
|
||||||
//
|
//
|
||||||
ObDereferenceObject(Process);
|
ObDereferenceObject(Process);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Enter SEH to return data
|
// Enter SEH to return data
|
||||||
//
|
//
|
||||||
|
@ -1956,7 +1955,7 @@ NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return status
|
// Return status
|
||||||
//
|
//
|
||||||
|
@ -1977,7 +1976,7 @@ NtFlushVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
SIZE_T CapturedBytesToFlush;
|
SIZE_T CapturedBytesToFlush;
|
||||||
IO_STATUS_BLOCK LocalStatusBlock;
|
IO_STATUS_BLOCK LocalStatusBlock;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we came from user mode
|
// Check if we came from user mode
|
||||||
//
|
//
|
||||||
|
@ -1994,7 +1993,7 @@ NtFlushVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
ProbeForWritePointer(BaseAddress);
|
ProbeForWritePointer(BaseAddress);
|
||||||
ProbeForWriteSize_t(NumberOfBytesToFlush);
|
ProbeForWriteSize_t(NumberOfBytesToFlush);
|
||||||
ProbeForWriteIoStatusBlock(IoStatusBlock);
|
ProbeForWriteIoStatusBlock(IoStatusBlock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Capture them
|
// Capture them
|
||||||
//
|
//
|
||||||
|
@ -2018,12 +2017,12 @@ NtFlushVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
CapturedBaseAddress = *BaseAddress;
|
CapturedBaseAddress = *BaseAddress;
|
||||||
CapturedBytesToFlush = *NumberOfBytesToFlush;
|
CapturedBytesToFlush = *NumberOfBytesToFlush;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Catch illegal base address
|
// Catch illegal base address
|
||||||
//
|
//
|
||||||
if (CapturedBaseAddress > MM_HIGHEST_USER_ADDRESS) return STATUS_INVALID_PARAMETER;
|
if (CapturedBaseAddress > MM_HIGHEST_USER_ADDRESS) return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Catch illegal region size
|
// Catch illegal region size
|
||||||
//
|
//
|
||||||
|
@ -2034,7 +2033,7 @@ NtFlushVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get a reference to the process
|
// Get a reference to the process
|
||||||
//
|
//
|
||||||
|
@ -2045,7 +2044,7 @@ NtFlushVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
(PVOID*)(&Process),
|
(PVOID*)(&Process),
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Do it
|
// Do it
|
||||||
//
|
//
|
||||||
|
@ -2053,12 +2052,12 @@ NtFlushVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
&CapturedBaseAddress,
|
&CapturedBaseAddress,
|
||||||
&CapturedBytesToFlush,
|
&CapturedBytesToFlush,
|
||||||
&LocalStatusBlock);
|
&LocalStatusBlock);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release reference
|
// Release reference
|
||||||
//
|
//
|
||||||
ObDereferenceObject(Process);
|
ObDereferenceObject(Process);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Enter SEH to return data
|
// Enter SEH to return data
|
||||||
//
|
//
|
||||||
|
@ -2075,7 +2074,7 @@ NtFlushVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return status
|
// Return status
|
||||||
//
|
//
|
||||||
|
@ -2101,7 +2100,7 @@ NtGetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
ULONG_PTR CapturedEntryCount;
|
ULONG_PTR CapturedEntryCount;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if we came from user mode
|
// Check if we came from user mode
|
||||||
//
|
//
|
||||||
|
@ -2116,7 +2115,7 @@ NtGetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
// Catch illegal base address
|
// Catch illegal base address
|
||||||
//
|
//
|
||||||
if (BaseAddress > MM_HIGHEST_USER_ADDRESS) return STATUS_INVALID_PARAMETER_2;
|
if (BaseAddress > MM_HIGHEST_USER_ADDRESS) return STATUS_INVALID_PARAMETER_2;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Catch illegal region size
|
// Catch illegal region size
|
||||||
//
|
//
|
||||||
|
@ -2127,23 +2126,23 @@ NtGetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
return STATUS_INVALID_PARAMETER_3;
|
return STATUS_INVALID_PARAMETER_3;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Validate all data
|
// Validate all data
|
||||||
//
|
//
|
||||||
ProbeForWriteSize_t(EntriesInUserAddressArray);
|
ProbeForWriteSize_t(EntriesInUserAddressArray);
|
||||||
ProbeForWriteUlong(Granularity);
|
ProbeForWriteUlong(Granularity);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Capture them
|
// Capture them
|
||||||
//
|
//
|
||||||
CapturedEntryCount = *EntriesInUserAddressArray;
|
CapturedEntryCount = *EntriesInUserAddressArray;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Must have a count
|
// Must have a count
|
||||||
//
|
//
|
||||||
if (CapturedEntryCount == 0) return STATUS_INVALID_PARAMETER_5;
|
if (CapturedEntryCount == 0) return STATUS_INVALID_PARAMETER_5;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Can't be larger than the maximum
|
// Can't be larger than the maximum
|
||||||
//
|
//
|
||||||
|
@ -2154,7 +2153,7 @@ NtGetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
return STATUS_INVALID_PARAMETER_5;
|
return STATUS_INVALID_PARAMETER_5;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Probe the actual array
|
// Probe the actual array
|
||||||
//
|
//
|
||||||
|
@ -2179,7 +2178,7 @@ NtGetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
CapturedEntryCount = *EntriesInUserAddressArray;
|
CapturedEntryCount = *EntriesInUserAddressArray;
|
||||||
ASSERT(CapturedEntryCount != 0);
|
ASSERT(CapturedEntryCount != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is a local request
|
// Check if this is a local request
|
||||||
//
|
//
|
||||||
|
@ -2190,7 +2189,7 @@ NtGetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
Process = PsGetCurrentProcess();
|
Process = PsGetCurrentProcess();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Reference the target
|
// Reference the target
|
||||||
|
@ -2203,7 +2202,7 @@ NtGetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Compute the last address and validate it
|
// Compute the last address and validate it
|
||||||
//
|
//
|
||||||
|
@ -2216,17 +2215,17 @@ NtGetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
|
if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
|
||||||
return STATUS_INVALID_PARAMETER_4;
|
return STATUS_INVALID_PARAMETER_4;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Oops :(
|
// Oops :(
|
||||||
//
|
//
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Dereference if needed
|
// Dereference if needed
|
||||||
//
|
//
|
||||||
if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
|
if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Enter SEH to return data
|
// Enter SEH to return data
|
||||||
//
|
//
|
||||||
|
@ -2246,7 +2245,7 @@ NtGetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
Status = _SEH2_GetExceptionCode();
|
Status = _SEH2_GetExceptionCode();
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return success
|
// Return success
|
||||||
//
|
//
|
||||||
|
@ -2267,12 +2266,12 @@ NtResetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
|
ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Catch illegal base address
|
// Catch illegal base address
|
||||||
//
|
//
|
||||||
if (BaseAddress > MM_HIGHEST_USER_ADDRESS) return STATUS_INVALID_PARAMETER_2;
|
if (BaseAddress > MM_HIGHEST_USER_ADDRESS) return STATUS_INVALID_PARAMETER_2;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Catch illegal region size
|
// Catch illegal region size
|
||||||
//
|
//
|
||||||
|
@ -2283,7 +2282,7 @@ NtResetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
return STATUS_INVALID_PARAMETER_3;
|
return STATUS_INVALID_PARAMETER_3;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is a local request
|
// Check if this is a local request
|
||||||
//
|
//
|
||||||
|
@ -2294,7 +2293,7 @@ NtResetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
//
|
//
|
||||||
Process = PsGetCurrentProcess();
|
Process = PsGetCurrentProcess();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Reference the target
|
// Reference the target
|
||||||
|
@ -2307,7 +2306,7 @@ NtResetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Compute the last address and validate it
|
// Compute the last address and validate it
|
||||||
//
|
//
|
||||||
|
@ -2320,17 +2319,17 @@ NtResetWriteWatch(IN HANDLE ProcessHandle,
|
||||||
if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
|
if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
|
||||||
return STATUS_INVALID_PARAMETER_3;
|
return STATUS_INVALID_PARAMETER_3;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Oops :(
|
// Oops :(
|
||||||
//
|
//
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Dereference if needed
|
// Dereference if needed
|
||||||
//
|
//
|
||||||
if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
|
if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return success
|
// Return success
|
||||||
//
|
//
|
||||||
|
@ -2420,7 +2419,7 @@ MiQueryMemoryBasicInformation(IN HANDLE ProcessHandle,
|
||||||
(PVOID*)&TargetProcess,
|
(PVOID*)&TargetProcess,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
/* Attach to it now */
|
/* Attach to it now */
|
||||||
KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
|
KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
|
||||||
}
|
}
|
||||||
|
@ -2542,14 +2541,14 @@ MiQueryMemoryBasicInformation(IN HANDLE ProcessHandle,
|
||||||
|
|
||||||
/* This must be a VM VAD */
|
/* This must be a VM VAD */
|
||||||
ASSERT(Vad->u.VadFlags.PrivateMemory);
|
ASSERT(Vad->u.VadFlags.PrivateMemory);
|
||||||
|
|
||||||
/* Build the initial information block */
|
/* Build the initial information block */
|
||||||
Address = PAGE_ALIGN(BaseAddress);
|
Address = PAGE_ALIGN(BaseAddress);
|
||||||
MemoryInfo.BaseAddress = Address;
|
MemoryInfo.BaseAddress = Address;
|
||||||
MemoryInfo.AllocationBase = (PVOID)(Vad->StartingVpn << PAGE_SHIFT);
|
MemoryInfo.AllocationBase = (PVOID)(Vad->StartingVpn << PAGE_SHIFT);
|
||||||
MemoryInfo.AllocationProtect = MmProtectToValue[Vad->u.VadFlags.Protection];
|
MemoryInfo.AllocationProtect = MmProtectToValue[Vad->u.VadFlags.Protection];
|
||||||
MemoryInfo.Type = MEM_PRIVATE;
|
MemoryInfo.Type = MEM_PRIVATE;
|
||||||
|
|
||||||
/* Find the largest chunk of memory which has the same state and protection mask */
|
/* Find the largest chunk of memory which has the same state and protection mask */
|
||||||
MemoryInfo.State = MiQueryAddressState(Address,
|
MemoryInfo.State = MiQueryAddressState(Address,
|
||||||
Vad,
|
Vad,
|
||||||
|
@ -2722,7 +2721,7 @@ NtQueryVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
return STATUS_INFO_LENGTH_MISMATCH;
|
return STATUS_INFO_LENGTH_MISMATCH;
|
||||||
}
|
}
|
||||||
Status = MiQueryMemoryBasicInformation(ProcessHandle,
|
Status = MiQueryMemoryBasicInformation(ProcessHandle,
|
||||||
BaseAddress,
|
BaseAddress,
|
||||||
MemoryInformation,
|
MemoryInformation,
|
||||||
MemoryInformationLength,
|
MemoryInformationLength,
|
||||||
ReturnLength);
|
ReturnLength);
|
||||||
|
@ -2736,7 +2735,7 @@ NtQueryVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
return STATUS_INFO_LENGTH_MISMATCH;
|
return STATUS_INFO_LENGTH_MISMATCH;
|
||||||
}
|
}
|
||||||
Status = MiQueryMemorySectionName(ProcessHandle,
|
Status = MiQueryMemorySectionName(ProcessHandle,
|
||||||
BaseAddress,
|
BaseAddress,
|
||||||
MemoryInformation,
|
MemoryInformation,
|
||||||
MemoryInformationLength,
|
MemoryInformationLength,
|
||||||
ReturnLength);
|
ReturnLength);
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::ZEROPAGE"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -35,7 +34,7 @@ MmZeroPageThread(VOID)
|
||||||
PVOID ZeroAddress;
|
PVOID ZeroAddress;
|
||||||
PFN_NUMBER PageIndex, FreePage;
|
PFN_NUMBER PageIndex, FreePage;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
|
|
||||||
/* FIXME: Get the discardable sections to free them */
|
/* FIXME: Get the discardable sections to free them */
|
||||||
// MiFindInitializationCode(&StartAddress, &EndAddress);
|
// MiFindInitializationCode(&StartAddress, &EndAddress);
|
||||||
// if (StartAddress) MiFreeInitializationCode(StartAddress, EndAddress);
|
// if (StartAddress) MiFreeInitializationCode(StartAddress, EndAddress);
|
||||||
|
@ -44,7 +43,7 @@ MmZeroPageThread(VOID)
|
||||||
/* Set our priority to 0 */
|
/* Set our priority to 0 */
|
||||||
Thread->BasePriority = 0;
|
Thread->BasePriority = 0;
|
||||||
KeSetPriorityThread(Thread, 0);
|
KeSetPriorityThread(Thread, 0);
|
||||||
|
|
||||||
/* Setup the wait objects */
|
/* Setup the wait objects */
|
||||||
WaitObjects[0] = &MmZeroingPageEvent;
|
WaitObjects[0] = &MmZeroingPageEvent;
|
||||||
// WaitObjects[1] = &PoSystemIdleTimer; FIXME: Implement idle timer
|
// WaitObjects[1] = &PoSystemIdleTimer; FIXME: Implement idle timer
|
||||||
|
@ -75,7 +74,7 @@ MmZeroPageThread(VOID)
|
||||||
MI_SET_USAGE(MI_USAGE_ZERO_LOOP);
|
MI_SET_USAGE(MI_USAGE_ZERO_LOOP);
|
||||||
MI_SET_PROCESS2("Kernel 0 Loop");
|
MI_SET_PROCESS2("Kernel 0 Loop");
|
||||||
FreePage = MiRemoveAnyPage(MI_GET_PAGE_COLOR(PageIndex));
|
FreePage = MiRemoveAnyPage(MI_GET_PAGE_COLOR(PageIndex));
|
||||||
|
|
||||||
/* The first global free page should also be the first on its own list */
|
/* The first global free page should also be the first on its own list */
|
||||||
if (FreePage != PageIndex)
|
if (FreePage != PageIndex)
|
||||||
{
|
{
|
||||||
|
@ -85,15 +84,15 @@ MmZeroPageThread(VOID)
|
||||||
PageIndex,
|
PageIndex,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pfn1->u1.Flink = LIST_HEAD;
|
Pfn1->u1.Flink = LIST_HEAD;
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
ZeroAddress = MiMapPagesToZeroInHyperSpace(Pfn1, 1);
|
ZeroAddress = MiMapPagesToZeroInHyperSpace(Pfn1, 1);
|
||||||
ASSERT(ZeroAddress);
|
ASSERT(ZeroAddress);
|
||||||
RtlZeroMemory(ZeroAddress, PAGE_SIZE);
|
RtlZeroMemory(ZeroAddress, PAGE_SIZE);
|
||||||
MiUnmapPagesInZeroSpace(ZeroAddress, 1);
|
MiUnmapPagesInZeroSpace(ZeroAddress, 1);
|
||||||
|
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
MiInsertPageInList(&MmZeroedPageListHead, PageIndex);
|
MiInsertPageInList(&MmZeroedPageListHead, PageIndex);
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#line 15 "ARM³::ARMPAGE"
|
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "../ARM3/miarm.h"
|
#include "../ARM3/miarm.h"
|
||||||
|
|
||||||
|
@ -329,7 +328,7 @@ MmInitGlobalKernelPageDirectory(VOID)
|
||||||
ULONG i;
|
ULONG i;
|
||||||
PULONG CurrentPageDirectory = (PULONG)PDE_BASE;
|
PULONG CurrentPageDirectory = (PULONG)PDE_BASE;
|
||||||
|
|
||||||
|
|
||||||
/* Loop the 2GB of address space which belong to the kernel */
|
/* Loop the 2GB of address space which belong to the kernel */
|
||||||
for (i = MiGetPdeOffset(MmSystemRangeStart); i < 2048; i++)
|
for (i = MiGetPdeOffset(MmSystemRangeStart); i < 2048; i++)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue