mirror of
https://github.com/reactos/reactos.git
synced 2024-10-03 07:53:49 +00:00
[NTOSKRNL]: Add more support for session space, including mapping and unmapping views into it, as well as putting in the correct checks in the page fault handler for future work.
[NTOSKRNL]: Cleanup the page fault handler to help with debugging, fix a few bugs and missing perf counters. There's a lot of cut corners that need some love, will be slowly adding more asserts/sanity code to make sure things are working right. svn path=/trunk/; revision=56926
This commit is contained in:
parent
f505107ac2
commit
5e1b6eac22
|
@ -117,12 +117,6 @@ MiInitializeSessionSpaceLayout()
|
||||||
MmSessionSize -
|
MmSessionSize -
|
||||||
MmSessionImageSize -
|
MmSessionImageSize -
|
||||||
MM_ALLOCATION_GRANULARITY);
|
MM_ALLOCATION_GRANULARITY);
|
||||||
|
|
||||||
/* Setup all starting addresses */
|
|
||||||
DPRINT1("Session space: 0x%p\n", MmSessionSpace);
|
|
||||||
DPRINT1("Session Base: 0x%p, Session Image Size: 0x%lx, Session Image Start: 0x%p, Session ImageEnd: 0x%p\n",
|
|
||||||
MmSessionBase, MmSessionSize, MiSessionImageStart, MiSessionImageEnd);
|
|
||||||
DPRINT1("Session View start: 0x%p, Session View Size: 0x%lx\n", MiSessionViewStart, MmSessionViewSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -1607,6 +1607,13 @@ MiInitializeSystemSpaceMap(
|
||||||
IN PMMSESSION InputSession OPTIONAL
|
IN PMMSESSION InputSession OPTIONAL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MiSessionCommitPageTables(
|
||||||
|
IN PVOID StartVa,
|
||||||
|
IN PVOID EndVa
|
||||||
|
);
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
NTAPI
|
NTAPI
|
||||||
MiMakeProtectionMask(
|
MiMakeProtectionMask(
|
||||||
|
|
|
@ -137,6 +137,11 @@ MiCheckPdeForPagedPool(IN PVOID Address)
|
||||||
PMMPDE PointerPde;
|
PMMPDE PointerPde;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (MI_IS_SESSION_ADDRESS(Address))
|
||||||
|
{
|
||||||
|
DPRINT1("Unexpected session fault: %p %p %p\n", Address, MmSessionBase, MiSessionSpaceEnd);
|
||||||
|
}
|
||||||
|
|
||||||
/* 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);
|
||||||
|
@ -874,16 +879,68 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
PMMVAD Vad;
|
PMMVAD Vad;
|
||||||
PFN_NUMBER PageFrameIndex;
|
PFN_NUMBER PageFrameIndex;
|
||||||
ULONG Color;
|
ULONG Color;
|
||||||
|
BOOLEAN IsSessionAddress;
|
||||||
|
PMMPFN Pfn1;
|
||||||
DPRINT("ARM3 FAULT AT: %p\n", Address);
|
DPRINT("ARM3 FAULT AT: %p\n", Address);
|
||||||
|
|
||||||
/* Check for page fault on high IRQL */
|
/* Check for page fault on high IRQL */
|
||||||
if (OldIrql > APC_LEVEL)
|
if (OldIrql > APC_LEVEL)
|
||||||
{
|
{
|
||||||
// There are some special cases where this is okay, but not in ARM3 yet
|
#if (_MI_PAGING_LEVELS < 3)
|
||||||
DbgPrint("MM:***PAGE FAULT AT IRQL > 1 Va %p, IRQL %lx\n",
|
/* Could be a page table for paged pool, which we'll allow */
|
||||||
Address,
|
if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)) MiSynchronizeSystemPde((PMMPDE)PointerPte);
|
||||||
OldIrql);
|
MiCheckPdeForPagedPool(Address);
|
||||||
ASSERT(OldIrql <= APC_LEVEL);
|
#endif
|
||||||
|
/* Check if any of the top-level pages are invalid */
|
||||||
|
if (
|
||||||
|
#if (_MI_PAGING_LEVELS == 4)
|
||||||
|
(PointerPxe->u.Hard.Valid == 0) ||
|
||||||
|
#endif
|
||||||
|
#if (_MI_PAGING_LEVELS >= 3)
|
||||||
|
(PointerPpe->u.Hard.Valid == 0) ||
|
||||||
|
#endif
|
||||||
|
(PointerPde->u.Hard.Valid == 0))
|
||||||
|
{
|
||||||
|
/* This fault is not valid, printf out some debugging help */
|
||||||
|
DbgPrint("MM:***PAGE FAULT AT IRQL > 1 Va %p, IRQL %lx\n",
|
||||||
|
Address,
|
||||||
|
OldIrql);
|
||||||
|
if (TrapInformation)
|
||||||
|
{
|
||||||
|
PKTRAP_FRAME TrapFrame = TrapInformation;
|
||||||
|
DbgPrint("MM:***EIP %p, EFL %p\n", TrapFrame->Eip, TrapFrame->EFlags);
|
||||||
|
DbgPrint("MM:***EAX %p, ECX %p EDX %p\n", TrapFrame->Eax, TrapFrame->Ecx, TrapFrame->Edx);
|
||||||
|
DbgPrint("MM:***EBX %p, ESI %p EDI %p\n", TrapFrame->Ebx, TrapFrame->Esi, TrapFrame->Edi);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tell the trap handler to fail */
|
||||||
|
return STATUS_IN_PAGE_ERROR | 0x10000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not yet implemented in ReactOS */
|
||||||
|
ASSERT(MI_IS_PAGE_LARGE(PointerPde) == FALSE);
|
||||||
|
ASSERT(((StoreInstruction) && (PointerPte->u.Hard.CopyOnWrite)) == FALSE);
|
||||||
|
|
||||||
|
/* Check if this was a write */
|
||||||
|
if (StoreInstruction)
|
||||||
|
{
|
||||||
|
/* Was it to a read-only page? */
|
||||||
|
Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
|
||||||
|
if (!(PointerPte->u.Long & PTE_READWRITE) &&
|
||||||
|
!(Pfn1->OriginalPte.u.Soft.Protection & MM_READWRITE))
|
||||||
|
{
|
||||||
|
/* Crash with distinguished bugcheck code */
|
||||||
|
KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
|
||||||
|
(ULONG_PTR)Address,
|
||||||
|
PointerPte->u.Long,
|
||||||
|
(ULONG_PTR)TrapInformation,
|
||||||
|
10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing is actually wrong */
|
||||||
|
DPRINT1("Fault at IRQL1 is ok\n");
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for kernel fault address */
|
/* Check for kernel fault address */
|
||||||
|
@ -892,77 +949,133 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
/* Bail out, if the fault came from user mode */
|
/* Bail out, if the fault came from user mode */
|
||||||
if (Mode == UserMode) return STATUS_ACCESS_VIOLATION;
|
if (Mode == UserMode) return STATUS_ACCESS_VIOLATION;
|
||||||
|
|
||||||
/* PXEs and PPEs for kernel mode are mapped for everything we need */
|
|
||||||
#if (_MI_PAGING_LEVELS >= 3)
|
|
||||||
if (
|
|
||||||
#if (_MI_PAGING_LEVELS == 4)
|
#if (_MI_PAGING_LEVELS == 4)
|
||||||
(PointerPxe->u.Hard.Valid == 0) ||
|
/* AMD64 system, check if PXE is invalid */
|
||||||
#endif
|
if (PointerPxe->u.Hard.Valid == 0)
|
||||||
(PointerPpe->u.Hard.Valid == 0))
|
|
||||||
{
|
{
|
||||||
/* The address is not from any pageable area! */
|
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
|
||||||
|
(ULONG_PTR)Address,
|
||||||
|
StoreInstruction,
|
||||||
|
(ULONG_PTR)TrapInformation,
|
||||||
|
7);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if (_MI_PAGING_LEVELS == 4)
|
||||||
|
/* PAE/AMD64 system, check if PPE is invalid */
|
||||||
|
if (PointerPpe->u.Hard.Valid == 0)
|
||||||
|
{
|
||||||
|
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
|
||||||
|
(ULONG_PTR)Address,
|
||||||
|
StoreInstruction,
|
||||||
|
(ULONG_PTR)TrapInformation,
|
||||||
|
5);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if (_MI_PAGING_LEVELS == 2)
|
||||||
|
if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)) MiSynchronizeSystemPde((PMMPDE)PointerPte);
|
||||||
|
MiCheckPdeForPagedPool(Address);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check if the PDE is invalid */
|
||||||
|
if (PointerPde->u.Hard.Valid == 0)
|
||||||
|
{
|
||||||
|
/* PDE (still) not valid, kill the system */
|
||||||
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
|
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
|
||||||
(ULONG_PTR)Address,
|
(ULONG_PTR)Address,
|
||||||
StoreInstruction,
|
StoreInstruction,
|
||||||
(ULONG_PTR)TrapInformation,
|
(ULONG_PTR)TrapInformation,
|
||||||
2);
|
2);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
/* Not handling session faults yet */
|
||||||
/* Check if we have a situation that might need synchronization
|
IsSessionAddress = MI_IS_SESSION_ADDRESS(Address);
|
||||||
of the PDE with the system page directory */
|
|
||||||
if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address))
|
|
||||||
{
|
|
||||||
/* This could be a paged pool commit with an unsychronized PDE.
|
|
||||||
NOTE: This way it works on x86, verify for other architectures! */
|
|
||||||
if (MiSynchronizeSystemPde((PMMPDE)PointerPte)) return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check if the PDE is invalid */
|
|
||||||
if (PointerPde->u.Hard.Valid == 0)
|
|
||||||
{
|
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
|
||||||
/* Sync this PDE and check, if that made it valid */
|
|
||||||
if (!MiSynchronizeSystemPde(PointerPde))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* PDE (still) not valid, kill the system */
|
|
||||||
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
|
|
||||||
(ULONG_PTR)Address,
|
|
||||||
StoreInstruction,
|
|
||||||
(ULONG_PTR)TrapInformation,
|
|
||||||
2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The PDE is valid, so read the PTE */
|
/* The PDE is valid, so read the PTE */
|
||||||
TempPte = *PointerPte;
|
TempPte = *PointerPte;
|
||||||
if (TempPte.u.Hard.Valid == 1)
|
if (TempPte.u.Hard.Valid == 1)
|
||||||
{
|
{
|
||||||
//
|
/* Check if this was system space or session space */
|
||||||
// Only two things can go wrong here:
|
if (!IsSessionAddress)
|
||||||
// Executing NX page (we couldn't care less)
|
{
|
||||||
// Writing to a read-only page (the stuff ARM3 works with is write,
|
/* Check if the PTE is still valid under PFN lock */
|
||||||
// so again, moot point).
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
//
|
TempPte = *PointerPte;
|
||||||
|
if (TempPte.u.Hard.Valid)
|
||||||
|
{
|
||||||
|
/* Check if this was a write */
|
||||||
|
if (StoreInstruction)
|
||||||
|
{
|
||||||
|
/* Was it to a read-only page? */
|
||||||
|
Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
|
||||||
|
if (!(PointerPte->u.Long & PTE_READWRITE) &&
|
||||||
|
!(Pfn1->OriginalPte.u.Soft.Protection & MM_READWRITE))
|
||||||
|
{
|
||||||
|
/* Crash with distinguished bugcheck code */
|
||||||
|
KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
|
||||||
|
(ULONG_PTR)Address,
|
||||||
|
PointerPte->u.Long,
|
||||||
|
(ULONG_PTR)TrapInformation,
|
||||||
|
11);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
/* Release PFN lock and return all good */
|
||||||
// Otherwise, the PDE was probably invalid, and all is good now
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
//
|
return STATUS_SUCCESS;
|
||||||
return STATUS_SUCCESS;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Not yet handled */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if this was a session PTE that needs to remap the session PDE */
|
||||||
|
if (MI_IS_SESSION_PTE(Address))
|
||||||
|
{
|
||||||
|
/* Not yet handled */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for a fault on the page table or hyperspace */
|
||||||
|
if (MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address))
|
||||||
|
{
|
||||||
|
#if (_MI_PAGING_LEVELS < 3)
|
||||||
|
/* Windows does this check but I don't understand why -- it's done above! */
|
||||||
|
ASSERT(MiCheckPdeForPagedPool(Address) != STATUS_WAIT_1);
|
||||||
|
#endif
|
||||||
|
/* Handle this as a user mode fault */
|
||||||
|
goto UserFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the current thread */
|
/* Get the current thread */
|
||||||
CurrentThread = PsGetCurrentThread();
|
CurrentThread = PsGetCurrentThread();
|
||||||
|
|
||||||
/* Check for a fault on the page table or hyperspace */
|
/* What kind of address is this */
|
||||||
if (MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address)) goto UserFault;
|
if (!IsSessionAddress)
|
||||||
|
{
|
||||||
|
/* Use the system working set */
|
||||||
|
WorkingSet = &MmSystemCacheWs;
|
||||||
|
CurrentProcess = NULL;
|
||||||
|
|
||||||
/* Use the system working set */
|
/* Make sure we don't have a recursive working set lock */
|
||||||
WorkingSet = &MmSystemCacheWs;
|
if ((CurrentThread->OwnsProcessWorkingSetExclusive) ||
|
||||||
CurrentProcess = NULL;
|
(CurrentThread->OwnsProcessWorkingSetShared) ||
|
||||||
|
(CurrentThread->OwnsSystemWorkingSetExclusive) ||
|
||||||
|
(CurrentThread->OwnsSystemWorkingSetShared) ||
|
||||||
|
(CurrentThread->OwnsSessionWorkingSetExclusive) ||
|
||||||
|
(CurrentThread->OwnsSessionWorkingSetShared))
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
return STATUS_IN_PAGE_ERROR | 0x10000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Not yet handled */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/* Acquire the working set lock */
|
/* Acquire the working set lock */
|
||||||
KeRaiseIrql(APC_LEVEL, &LockIrql);
|
KeRaiseIrql(APC_LEVEL, &LockIrql);
|
||||||
|
@ -972,17 +1085,35 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
TempPte = *PointerPte;
|
TempPte = *PointerPte;
|
||||||
if (TempPte.u.Hard.Valid == 1)
|
if (TempPte.u.Hard.Valid == 1)
|
||||||
{
|
{
|
||||||
// Only two things can go wrong here:
|
/* Check if this was a write */
|
||||||
// Executing NX page (we couldn't care less)
|
if (StoreInstruction)
|
||||||
// Writing to a read-only page (the stuff ARM3 works with is write,
|
{
|
||||||
// so again, moot point).
|
/* Was it to a read-only page that is not copy on write? */
|
||||||
ASSERT(TempPte.u.Hard.Write == 1);
|
Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
|
||||||
|
if (!(TempPte.u.Long & PTE_READWRITE) &&
|
||||||
|
!(Pfn1->OriginalPte.u.Soft.Protection & MM_READWRITE) &&
|
||||||
|
!(TempPte.u.Hard.CopyOnWrite))
|
||||||
|
{
|
||||||
|
/* Case not yet handled */
|
||||||
|
ASSERT(!IsSessionAddress);
|
||||||
|
|
||||||
|
/* Crash with distinguished bugcheck code */
|
||||||
|
KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
|
||||||
|
(ULONG_PTR)Address,
|
||||||
|
TempPte.u.Long,
|
||||||
|
(ULONG_PTR)TrapInformation,
|
||||||
|
12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Case not yet handled */
|
||||||
|
ASSERT(!IsSessionAddress);
|
||||||
|
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1007,6 +1138,9 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
|
|
||||||
/* Get the prototype PTE! */
|
/* Get the prototype PTE! */
|
||||||
ProtoPte = MiProtoPteToPte(&TempPte);
|
ProtoPte = MiProtoPteToPte(&TempPte);
|
||||||
|
|
||||||
|
/* Case not yet handled */
|
||||||
|
ASSERT(!IsSessionAddress);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1023,20 +1157,24 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
(ULONG_PTR)TrapInformation,
|
(ULONG_PTR)TrapInformation,
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for demand page */
|
/* Check for demand page */
|
||||||
if ((StoreInstruction) && !(TempPte.u.Hard.Valid))
|
if ((StoreInstruction) &&
|
||||||
|
!(ProtoPte) &&
|
||||||
|
!(IsSessionAddress) &&
|
||||||
|
!(TempPte.u.Hard.Valid))
|
||||||
|
{
|
||||||
|
/* Get the protection code */
|
||||||
|
ASSERT(TempPte.u.Soft.Transition == 0);
|
||||||
|
if (!(TempPte.u.Soft.Protection & MM_READWRITE))
|
||||||
{
|
{
|
||||||
/* Get the protection code */
|
/* Bugcheck the system! */
|
||||||
if (!(TempPte.u.Soft.Protection & MM_READWRITE))
|
KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
|
||||||
{
|
(ULONG_PTR)Address,
|
||||||
/* Bugcheck the system! */
|
TempPte.u.Long,
|
||||||
KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
|
(ULONG_PTR)TrapInformation,
|
||||||
(ULONG_PTR)Address,
|
14);
|
||||||
TempPte.u.Long,
|
|
||||||
(ULONG_PTR)TrapInformation,
|
|
||||||
14);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1068,10 +1206,6 @@ UserFault:
|
||||||
/* Lock the working set */
|
/* Lock the working set */
|
||||||
MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
|
MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
|
||||||
|
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
|
||||||
ASSERT(PointerPde->u.Hard.LargePage == 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (_MI_PAGING_LEVELS == 4)
|
#if (_MI_PAGING_LEVELS == 4)
|
||||||
// Note to Timo: You should call MiCheckVirtualAddress and also check if it's zero pte
|
// Note to Timo: You should call MiCheckVirtualAddress and also check if it's zero pte
|
||||||
// also this is missing the page count increment
|
// also this is missing the page count increment
|
||||||
|
@ -1156,6 +1290,11 @@ UserFault:
|
||||||
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
||||||
ASSERT(PointerPde->u.Hard.Valid == 1);
|
ASSERT(PointerPde->u.Hard.Valid == 1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Not yet implemented in ReactOS */
|
||||||
|
ASSERT(MI_IS_PAGE_LARGE(PointerPde) == FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/* Now capture the PTE. Ignore virtual faults for now */
|
/* Now capture the PTE. Ignore virtual faults for now */
|
||||||
TempPte = *PointerPte;
|
TempPte = *PointerPte;
|
||||||
|
@ -1175,141 +1314,125 @@ UserFault:
|
||||||
return STATUS_PAGE_FAULT_DEMAND_ZERO;
|
return STATUS_PAGE_FAULT_DEMAND_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure it's not a prototype PTE */
|
/* Check for zero PTE */
|
||||||
ASSERT(TempPte.u.Soft.Prototype == 0);
|
if (TempPte.u.Long == 0)
|
||||||
|
|
||||||
/* Check if this address range belongs to a valid allocation (VAD) */
|
|
||||||
ProtoPte = MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
|
|
||||||
if (ProtectionCode == MM_NOACCESS)
|
|
||||||
{
|
{
|
||||||
|
/* Check if this address range belongs to a valid allocation (VAD) */
|
||||||
|
ProtoPte = MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
|
||||||
|
if (ProtectionCode == MM_NOACCESS)
|
||||||
|
{
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
#if (_MI_PAGING_LEVELS == 2)
|
||||||
/* Could be a page table for paged pool */
|
/* Could be a page table for paged pool */
|
||||||
MiCheckPdeForPagedPool(Address);
|
MiCheckPdeForPagedPool(Address);
|
||||||
#endif
|
#endif
|
||||||
/* Has the code above changed anything -- is this now a valid PTE? */
|
/* Has the code above changed anything -- is this now a valid PTE? */
|
||||||
Status = (PointerPte->u.Hard.Valid == 1) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
|
Status = (PointerPte->u.Hard.Valid == 1) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
|
||||||
|
|
||||||
/* Either this was a bogus VA or we've fixed up a paged pool PDE */
|
/* Either this was a bogus VA or we've fixed up a paged pool PDE */
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for non-demand zero PTE */
|
|
||||||
if (TempPte.u.Long != 0)
|
|
||||||
{
|
|
||||||
/* This is a page fault */
|
|
||||||
|
|
||||||
/* FIXME: Run MiAccessCheck */
|
|
||||||
|
|
||||||
/* Dispatch the fault */
|
|
||||||
Status = MiDispatchFault(StoreInstruction,
|
|
||||||
Address,
|
|
||||||
PointerPte,
|
|
||||||
NULL,
|
|
||||||
FALSE,
|
|
||||||
PsGetCurrentProcess(),
|
|
||||||
TrapInformation,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
/* Return the status */
|
|
||||||
ASSERT(NT_SUCCESS(Status));
|
|
||||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if this is a real user-mode address or actually a kernel-mode
|
|
||||||
* page table for a user mode address
|
|
||||||
*/
|
|
||||||
if (Address <= MM_HIGHEST_USER_ADDRESS)
|
|
||||||
{
|
|
||||||
/* Add an additional page table reference */
|
|
||||||
MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
|
|
||||||
ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No guard page support yet */
|
|
||||||
ASSERT((ProtectionCode & MM_DECOMMIT) == 0);
|
|
||||||
|
|
||||||
/* Did we get a prototype PTE back? */
|
|
||||||
if (!ProtoPte)
|
|
||||||
{
|
|
||||||
/* Is this PTE actually part of the PDE-PTE self-mapping directory? */
|
|
||||||
if (PointerPde == MiAddressToPde(PTE_BASE))
|
|
||||||
{
|
|
||||||
/* Then it's really a demand-zero PDE (on behalf of user-mode) */
|
|
||||||
MI_WRITE_INVALID_PTE(PointerPte, DemandZeroPde);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* No, create a new PTE. First, write the protection */
|
|
||||||
PointerPte->u.Soft.Protection = ProtectionCode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the PFN database since we're going to grab a page */
|
/* No guard page support yet */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
ASSERT((ProtectionCode & MM_DECOMMIT) == 0);
|
||||||
|
|
||||||
/* Try to get a zero page */
|
/*
|
||||||
MI_SET_USAGE(MI_USAGE_PEB_TEB);
|
* Check if this is a real user-mode address or actually a kernel-mode
|
||||||
MI_SET_PROCESS2(CurrentProcess->ImageFileName);
|
* page table for a user mode address
|
||||||
Color = MI_GET_NEXT_PROCESS_COLOR(CurrentProcess);
|
*/
|
||||||
PageFrameIndex = MiRemoveZeroPageSafe(Color);
|
if (Address <= MM_HIGHEST_USER_ADDRESS)
|
||||||
if (!PageFrameIndex)
|
|
||||||
{
|
{
|
||||||
/* Grab a page out of there. Later we should grab a colored zero page */
|
/* Add an additional page table reference */
|
||||||
PageFrameIndex = MiRemoveAnyPage(Color);
|
MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
|
||||||
ASSERT(PageFrameIndex);
|
ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
/* Release the lock since we need to do some zeroing */
|
/* Did we get a prototype PTE back? */
|
||||||
|
if (!ProtoPte)
|
||||||
|
{
|
||||||
|
/* Is this PTE actually part of the PDE-PTE self-mapping directory? */
|
||||||
|
if (PointerPde == MiAddressToPde(PTE_BASE))
|
||||||
|
{
|
||||||
|
/* Then it's really a demand-zero PDE (on behalf of user-mode) */
|
||||||
|
MI_WRITE_INVALID_PTE(PointerPte, DemandZeroPde);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No, create a new PTE. First, write the protection */
|
||||||
|
PointerPte->u.Soft.Protection = ProtectionCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock the PFN database since we're going to grab a page */
|
||||||
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
|
/* Make sure we have enough pages */
|
||||||
|
ASSERT(MmAvailablePages >= 32);
|
||||||
|
|
||||||
|
/* Try to get a zero page */
|
||||||
|
MI_SET_USAGE(MI_USAGE_PEB_TEB);
|
||||||
|
MI_SET_PROCESS2(CurrentProcess->ImageFileName);
|
||||||
|
Color = MI_GET_NEXT_PROCESS_COLOR(CurrentProcess);
|
||||||
|
PageFrameIndex = MiRemoveZeroPageSafe(Color);
|
||||||
|
if (!PageFrameIndex)
|
||||||
|
{
|
||||||
|
/* Grab a page out of there. Later we should grab a colored zero page */
|
||||||
|
PageFrameIndex = MiRemoveAnyPage(Color);
|
||||||
|
ASSERT(PageFrameIndex);
|
||||||
|
|
||||||
|
/* Release the lock since we need to do some zeroing */
|
||||||
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
|
/* Zero out the page, since it's for user-mode */
|
||||||
|
MiZeroPfn(PageFrameIndex);
|
||||||
|
|
||||||
|
/* Grab the lock again so we can initialize the PFN entry */
|
||||||
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the PFN entry now */
|
||||||
|
MiInitializePfn(PageFrameIndex, PointerPte, 1);
|
||||||
|
|
||||||
|
/* And we're done with the lock */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
/* Zero out the page, since it's for user-mode */
|
/* Increment the count of pages in the process */
|
||||||
MiZeroPfn(PageFrameIndex);
|
CurrentProcess->NumberOfPrivatePages++;
|
||||||
|
|
||||||
/* Grab the lock again so we can initialize the PFN entry */
|
/* One more demand-zero fault */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
InterlockedIncrement(&KeGetCurrentPrcb()->MmDemandZeroCount);
|
||||||
|
|
||||||
|
/* Fault on user PDE, or fault on user PTE? */
|
||||||
|
if (PointerPte <= MiHighestUserPte)
|
||||||
|
{
|
||||||
|
/* User fault, build a user PTE */
|
||||||
|
MI_MAKE_HARDWARE_PTE_USER(&TempPte,
|
||||||
|
PointerPte,
|
||||||
|
PointerPte->u.Soft.Protection,
|
||||||
|
PageFrameIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This is a user-mode PDE, create a kernel PTE for it */
|
||||||
|
MI_MAKE_HARDWARE_PTE(&TempPte,
|
||||||
|
PointerPte,
|
||||||
|
PointerPte->u.Soft.Protection,
|
||||||
|
PageFrameIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the dirty bit for writeable pages */
|
||||||
|
if (MI_IS_PAGE_WRITEABLE(&TempPte)) MI_MAKE_DIRTY_PAGE(&TempPte);
|
||||||
|
|
||||||
|
/* And now write down the PTE, making the address valid */
|
||||||
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
||||||
|
ASSERT(Pfn1->u1.Event == NULL);
|
||||||
|
|
||||||
|
/* Demand zero */
|
||||||
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||||
|
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
||||||
|
return STATUS_PAGE_FAULT_DEMAND_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the PFN entry now */
|
|
||||||
MiInitializePfn(PageFrameIndex, PointerPte, 1);
|
|
||||||
|
|
||||||
/* One more demand-zero fault */
|
|
||||||
KeGetCurrentPrcb()->MmDemandZeroCount++;
|
|
||||||
|
|
||||||
/* And we're done with the lock */
|
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
|
||||||
|
|
||||||
/* Fault on user PDE, or fault on user PTE? */
|
|
||||||
if (PointerPte <= MiHighestUserPte)
|
|
||||||
{
|
|
||||||
/* User fault, build a user PTE */
|
|
||||||
MI_MAKE_HARDWARE_PTE_USER(&TempPte,
|
|
||||||
PointerPte,
|
|
||||||
PointerPte->u.Soft.Protection,
|
|
||||||
PageFrameIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This is a user-mode PDE, create a kernel PTE for it */
|
|
||||||
MI_MAKE_HARDWARE_PTE(&TempPte,
|
|
||||||
PointerPte,
|
|
||||||
PointerPte->u.Soft.Protection,
|
|
||||||
PageFrameIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write the dirty bit for writeable pages */
|
|
||||||
if (MI_IS_PAGE_WRITEABLE(&TempPte)) MI_MAKE_DIRTY_PAGE(&TempPte);
|
|
||||||
|
|
||||||
/* And now write down the PTE, making the address valid */
|
|
||||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
|
||||||
ASSERT(MiGetPfnEntry(PageFrameIndex)->u1.Event == NULL);
|
|
||||||
|
|
||||||
/* Demand zero */
|
|
||||||
Status = STATUS_PAGE_FAULT_DEMAND_ZERO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 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);
|
||||||
|
@ -1318,22 +1441,28 @@ UserFault:
|
||||||
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 */
|
else
|
||||||
Status = MiDispatchFault(StoreInstruction,
|
{
|
||||||
Address,
|
/* This path is not yet supported */
|
||||||
PointerPte,
|
ASSERT(FALSE);
|
||||||
ProtoPte,
|
|
||||||
FALSE,
|
|
||||||
CurrentProcess,
|
|
||||||
TrapInformation,
|
|
||||||
Vad);
|
|
||||||
ASSERT(Status == STATUS_PAGE_FAULT_TRANSITION);
|
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 1);
|
|
||||||
ASSERT(PointerPte->u.Hard.PageFrameNumber != 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the working set */
|
/* FIXME: Run MiAccessCheck */
|
||||||
|
|
||||||
|
/* Dispatch the fault */
|
||||||
|
Status = MiDispatchFault(StoreInstruction,
|
||||||
|
Address,
|
||||||
|
PointerPte,
|
||||||
|
ProtoPte,
|
||||||
|
FALSE,
|
||||||
|
CurrentProcess,
|
||||||
|
TrapInformation,
|
||||||
|
Vad);
|
||||||
|
|
||||||
|
/* Return the status */
|
||||||
|
ASSERT(NT_SUCCESS(Status));
|
||||||
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,7 +243,9 @@ MiInitializeSystemSpaceMap(IN PMMSESSION InputSession OPTIONAL)
|
||||||
ASSERT(AllocSize < PAGE_SIZE);
|
ASSERT(AllocSize < PAGE_SIZE);
|
||||||
|
|
||||||
/* Allocate and zero the view table */
|
/* Allocate and zero the view table */
|
||||||
Session->SystemSpaceViewTable = ExAllocatePoolWithTag(NonPagedPool,
|
Session->SystemSpaceViewTable = ExAllocatePoolWithTag(Session == &MmSession ?
|
||||||
|
NonPagedPool :
|
||||||
|
PagedPool,
|
||||||
AllocSize,
|
AllocSize,
|
||||||
TAG_MM);
|
TAG_MM);
|
||||||
ASSERT(Session->SystemSpaceViewTable != NULL);
|
ASSERT(Session->SystemSpaceViewTable != NULL);
|
||||||
|
@ -264,9 +266,6 @@ MiInsertInSystemSpace(IN PMMSESSION Session,
|
||||||
PMMVIEW OldTable;
|
PMMVIEW OldTable;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Only global mappings supported for now */
|
|
||||||
ASSERT(Session == &MmSession);
|
|
||||||
|
|
||||||
/* Stay within 4GB */
|
/* Stay within 4GB */
|
||||||
ASSERT(Buckets < MI_SYSTEM_VIEW_BUCKET_SIZE);
|
ASSERT(Buckets < MI_SYSTEM_VIEW_BUCKET_SIZE);
|
||||||
|
|
||||||
|
@ -281,7 +280,10 @@ MiInsertInSystemSpace(IN PMMSESSION Session,
|
||||||
|
|
||||||
/* Save the old table and allocate a new one */
|
/* Save the old table and allocate a new one */
|
||||||
OldTable = Session->SystemSpaceViewTable;
|
OldTable = Session->SystemSpaceViewTable;
|
||||||
Session->SystemSpaceViewTable = ExAllocatePoolWithTag(NonPagedPool,
|
Session->SystemSpaceViewTable = ExAllocatePoolWithTag(Session ==
|
||||||
|
&MmSession ?
|
||||||
|
NonPagedPool :
|
||||||
|
PagedPool,
|
||||||
HashSize *
|
HashSize *
|
||||||
sizeof(MMVIEW),
|
sizeof(MMVIEW),
|
||||||
' mM');
|
' mM');
|
||||||
|
@ -804,6 +806,111 @@ Quickie:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MiSessionCommitPageTables(IN PVOID StartVa,
|
||||||
|
IN PVOID EndVa)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
ULONG Color, Index;
|
||||||
|
PMMPTE StartPde, EndPde;
|
||||||
|
MMPTE TempPte = ValidKernelPdeLocal;
|
||||||
|
PMMPFN Pfn1;
|
||||||
|
PFN_NUMBER PageCount = 0, ActualPages = 0, PageFrameNumber;
|
||||||
|
|
||||||
|
/* Windows sanity checks */
|
||||||
|
ASSERT(StartVa >= (PVOID)MmSessionBase);
|
||||||
|
ASSERT(EndVa < (PVOID)MiSessionSpaceEnd);
|
||||||
|
ASSERT(PAGE_ALIGN(EndVa) == EndVa);
|
||||||
|
|
||||||
|
/* Get the start and end PDE, then loop each one */
|
||||||
|
StartPde = MiAddressToPde(StartVa);
|
||||||
|
EndPde = MiAddressToPde((PVOID)((ULONG_PTR)EndVa - 1));
|
||||||
|
Index = (ULONG_PTR)StartVa >> 22;
|
||||||
|
while (StartPde <= EndPde)
|
||||||
|
{
|
||||||
|
/* If we don't already have a page table for it, increment count */
|
||||||
|
if (MmSessionSpace->PageTables[Index].u.Long == 0) PageCount++;
|
||||||
|
|
||||||
|
/* Move to the next one */
|
||||||
|
StartPde++;
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there's no page tables to create, bail out */
|
||||||
|
if (PageCount == 0) return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
/* Reset the start PDE and index */
|
||||||
|
StartPde = MiAddressToPde(StartVa);
|
||||||
|
Index = (ULONG_PTR)StartVa >> 22;
|
||||||
|
|
||||||
|
/* Loop each PDE while holding the working set lock */
|
||||||
|
// MiLockWorkingSet(PsGetCurrentThread(),
|
||||||
|
// &MmSessionSpace->GlobalVirtualAddress->Vm);
|
||||||
|
while (StartPde <= EndPde)
|
||||||
|
{
|
||||||
|
/* Check if we already have a page table */
|
||||||
|
if (MmSessionSpace->PageTables[Index].u.Long == 0)
|
||||||
|
{
|
||||||
|
/* We don't, so the PDE shouldn't be ready yet */
|
||||||
|
ASSERT(StartPde->u.Hard.Valid == 0);
|
||||||
|
|
||||||
|
/* ReactOS check to avoid MiEnsureAvailablePageOrWait */
|
||||||
|
ASSERT(MmAvailablePages >= 32);
|
||||||
|
|
||||||
|
/* Acquire the PFN lock and grab a zero page */
|
||||||
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
Color = (++MmSessionSpace->Color) & MmSecondaryColorMask;
|
||||||
|
PageFrameNumber = MiRemoveZeroPage(Color);
|
||||||
|
TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
|
||||||
|
MI_WRITE_VALID_PTE(StartPde, TempPte);
|
||||||
|
|
||||||
|
/* Write the page table in session space structure */
|
||||||
|
ASSERT(MmSessionSpace->PageTables[Index].u.Long == 0);
|
||||||
|
MmSessionSpace->PageTables[Index] = TempPte;
|
||||||
|
|
||||||
|
/* Initialize the PFN */
|
||||||
|
MiInitializePfnForOtherProcess(PageFrameNumber,
|
||||||
|
StartPde,
|
||||||
|
MmSessionSpace->SessionPageDirectoryIndex);
|
||||||
|
|
||||||
|
/* And now release the lock */
|
||||||
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
|
/* Get the PFN entry and make sure there's no event for it */
|
||||||
|
Pfn1 = MI_PFN_ELEMENT(PageFrameNumber);
|
||||||
|
ASSERT(Pfn1->u1.Event == NULL);
|
||||||
|
|
||||||
|
/* Increment the number of pages */
|
||||||
|
ActualPages++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to the next PDE */
|
||||||
|
StartPde++;
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we didn't do more pages than expected */
|
||||||
|
ASSERT(ActualPages <= PageCount);
|
||||||
|
|
||||||
|
/* Release the working set lock */
|
||||||
|
// MiUnlockWorkingSet(PsGetCurrentThread(),
|
||||||
|
// &MmSessionSpace->GlobalVirtualAddress->Vm);
|
||||||
|
|
||||||
|
|
||||||
|
/* If we did at least one page... */
|
||||||
|
if (ActualPages)
|
||||||
|
{
|
||||||
|
/* Update the performance counters! */
|
||||||
|
InterlockedExchangeAddSizeT(&MmSessionSpace->NonPageablePages, ActualPages);
|
||||||
|
InterlockedExchangeAddSizeT(&MmSessionSpace->CommittedPages, ActualPages);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MiMapViewInSystemSpace(IN PVOID Section,
|
MiMapViewInSystemSpace(IN PVOID Section,
|
||||||
|
@ -817,9 +924,6 @@ MiMapViewInSystemSpace(IN PVOID Section,
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Only global mappings for now */
|
|
||||||
ASSERT(Session == &MmSession);
|
|
||||||
|
|
||||||
/* Get the control area, check for any flags ARM3 doesn't yet support */
|
/* Get the control area, check for any flags ARM3 doesn't yet support */
|
||||||
ControlArea = ((PSECTION)Section)->Segment->ControlArea;
|
ControlArea = ((PSECTION)Section)->Segment->ControlArea;
|
||||||
ASSERT(ControlArea->u.Flags.Image == 0);
|
ASSERT(ControlArea->u.Flags.Image == 0);
|
||||||
|
@ -860,8 +964,21 @@ MiMapViewInSystemSpace(IN PVOID Section,
|
||||||
Base = MiInsertInSystemSpace(Session, Buckets, ControlArea);
|
Base = MiInsertInSystemSpace(Session, Buckets, ControlArea);
|
||||||
ASSERT(Base);
|
ASSERT(Base);
|
||||||
|
|
||||||
/* Create the PDEs needed for this mapping, and double-map them if needed */
|
/* What's the underlying session? */
|
||||||
MiFillSystemPageDirectory(Base, Buckets * MI_SYSTEM_VIEW_BUCKET_SIZE);
|
if (Session == &MmSession)
|
||||||
|
{
|
||||||
|
/* Create the PDEs needed for this mapping, and double-map them if needed */
|
||||||
|
MiFillSystemPageDirectory(Base, Buckets * MI_SYSTEM_VIEW_BUCKET_SIZE);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Create the PDEs needed for this mapping */
|
||||||
|
Status = MiSessionCommitPageTables(Base,
|
||||||
|
(PVOID)((ULONG_PTR)Base +
|
||||||
|
Buckets * MI_SYSTEM_VIEW_BUCKET_SIZE));
|
||||||
|
NT_ASSERT(NT_SUCCESS(Status));
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the actual prototype PTEs for this mapping */
|
/* Create the actual prototype PTEs for this mapping */
|
||||||
Status = MiAddMappedPtes(MiAddressToPte(Base),
|
Status = MiAddMappedPtes(MiAddressToPte(Base),
|
||||||
|
@ -2213,6 +2330,7 @@ MmMapViewInSessionSpace(IN PVOID Section,
|
||||||
|
|
||||||
/* Use the system space API, but with the session view instead */
|
/* Use the system space API, but with the session view instead */
|
||||||
ASSERT(MmIsAddressValid(MmSessionSpace) == TRUE);
|
ASSERT(MmIsAddressValid(MmSessionSpace) == TRUE);
|
||||||
|
ASSERT(FALSE);
|
||||||
return MiMapViewInSystemSpace(Section,
|
return MiMapViewInSystemSpace(Section,
|
||||||
&MmSessionSpace->Session,
|
&MmSessionSpace->Session,
|
||||||
MappedBase,
|
MappedBase,
|
||||||
|
|
Loading…
Reference in a new issue