return MmSharedUserDataPte;
}
- /* Find the VAD, it must exist, since we only handle PEB/TEB */
+ /* Find the VAD, it might not exist if the address is bogus */
Vad = MiLocateAddress(VirtualAddress);
- ASSERT(Vad);
+ if (!Vad)
+ {
+ /* Bogus virtual address */
+ *ProtectCode = MM_NOACCESS;
+ return NULL;
+ }
/* This must be a TEB/PEB VAD */
ASSERT(Vad->u.VadFlags.PrivateMemory == TRUE);
//
if (PointerPde->u.Hard.Valid == 0)
{
-#ifndef _M_AMD64
- /* This seems to be making the assumption that one PDE is one page long */
- C_ASSERT(PAGE_SIZE == (PD_COUNT * (sizeof(MMPTE) * PDE_COUNT)));
-#endif
-
+#ifdef _M_AMD64
+ ASSERT(FALSE);
+#else
//
// Copy it from our double-mapped system page directory
//
InterlockedExchangePte(PointerPde,
- MmSystemPagePtes[((ULONG_PTR)PointerPde &
- (PAGE_SIZE - 1)) /
- sizeof(MMPTE)].u.Long);
+ MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)].u.Long);
+#endif
}
//
IN PEPROCESS Process,
IN KIRQL OldIrql)
{
- PFN_NUMBER PageFrameNumber;
+ PFN_NUMBER PageFrameNumber = 0;
MMPTE TempPte;
BOOLEAN NeedZero = FALSE;
+ ULONG Color;
DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n",
Address,
Process);
/* No forking yet */
ASSERT(Process->ForkInProgress == NULL);
+ /* Get process color */
+ Color = MI_GET_NEXT_PROCESS_COLOR(Process);
+
/* We'll need a zero page */
NeedZero = TRUE;
}
+ else
+ {
+ /* Get the next system page color */
+ Color = MI_GET_NEXT_COLOR();
+ }
//
// Lock the PFN database
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
ASSERT(PointerPte->u.Hard.Valid == 0);
- /* Get a page */
- PageFrameNumber = MiRemoveAnyPage(0);
- DPRINT("New pool page: %lx\n", PageFrameNumber);
+ /* Do we need a zero page? */
+ if (NeedZero)
+ {
+ /* Try to get one, if we couldn't grab a free page and zero it */
+ PageFrameNumber = MiRemoveZeroPageSafe(Color);
+ if (PageFrameNumber) NeedZero = FALSE;
+ }
+
+ /* Did we get a page? */
+ if (!PageFrameNumber)
+ {
+ /* We either failed to find a zero page, or this is a system request */
+ PageFrameNumber = MiRemoveAnyPage(Color);
+ DPRINT("New pool page: %lx\n", PageFrameNumber);
+ }
/* Initialize it */
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
ULONG ProtectionCode;
PMMVAD Vad;
PFN_NUMBER PageFrameIndex;
+ ULONG Color;
DPRINT("ARM3 FAULT AT: %p\n", Address);
//
//
PointerPte = MiAddressToPte(Address);
PointerPde = MiAddressToPde(Address);
-
+#if (_MI_PAGING_LEVELS >= 3)
+ /* We need the PPE and PXE addresses */
+ ASSERT(FALSE);
+#endif
+
//
// Check for dispatch-level snafu
//
//
if (Mode == UserMode) return STATUS_ACCESS_VIOLATION;
+#if (_MI_PAGING_LEVELS >= 3)
+ /* Need to check PXE and PDE validity */
+ ASSERT(FALSE);
+#endif
+
//
// Is the PDE valid?
//
// Debug spew (eww!)
//
DPRINT("Invalid PDE\n");
-
+#if (_MI_PAGING_LEVELS == 2)
//
// Handle mapping in "Special" PDE directoreis
//
MiCheckPdeForPagedPool(Address);
-
+#endif
//
// Now we SHOULD be good
//
// This might happen...not sure yet
//
DPRINT1("FAULT ON PAGE TABLES: %p %lx %lx!\n", Address, *PointerPte, *PointerPde);
-
+#if (_MI_PAGING_LEVELS == 2)
//
// Map in the page table
//
DPRINT1("PAGE TABLES FAULTED IN!\n");
return STATUS_SUCCESS;
}
-
+#endif
//
// Otherwise the page table doesn't actually exist
//
return STATUS_SUCCESS;
}
- //
- // We don't implement prototype PTEs
- //
- ASSERT(TempPte.u.Soft.Prototype == 0);
+ /* Check one kind of prototype PTE */
+ if (TempPte.u.Soft.Prototype)
+ {
+ /* The one used for protected pool... */
+ ASSERT(MmProtectFreedNonPagedPool == TRUE);
+
+ /* Make sure protected pool is on, and that this is a pool address */
+ if ((MmProtectFreedNonPagedPool) &&
+ (((Address >= MmNonPagedPoolStart) &&
+ (Address < (PVOID)((ULONG_PTR)MmNonPagedPoolStart +
+ MmSizeOfNonPagedPoolInBytes))) ||
+ ((Address >= MmNonPagedPoolExpansionStart) &&
+ (Address < MmNonPagedPoolEnd))))
+ {
+ /* Bad boy, bad boy, whatcha gonna do, whatcha gonna do when ARM3 comes for you! */
+ KeBugCheckEx(DRIVER_CAUGHT_MODIFYING_FREED_POOL,
+ (ULONG_PTR)Address,
+ StoreInstruction,
+ Mode,
+ 4);
+ }
+ }
//
// We don't implement transition PTEs
/* Lock the working set */
MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
+#if (_MI_PAGING_LEVELS >= 3)
+ /* Need to check/handle PPE and PXE validity too */
+ ASSERT(FALSE);
+#endif
+
/* First things first, is the PDE valid? */
ASSERT(PointerPde != MiAddressToPde(PTE_BASE));
ASSERT(PointerPde->u.Hard.LargePage == 0);
/* We should come back with APCs enabled, and with a valid PDE */
ASSERT(KeAreAllApcsDisabled() == TRUE);
+#if (_MI_PAGING_LEVELS >= 3)
+ /* Need to check/handle PPE and PXE validity too */
+ ASSERT(FALSE);
+#endif
ASSERT(PointerPde->u.Hard.Valid == 1);
}
/* Check if this address range belongs to a valid allocation (VAD) */
ProtoPte = MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
- ASSERT(ProtectionCode != MM_NOACCESS);
-
+ if (ProtectionCode == MM_NOACCESS)
+ {
+ /* This is a bogus VA */
+ Status = STATUS_ACCESS_VIOLATION;
+
+ /* Could be a not-yet-mapped paged pool page table */
+#if (_MI_PAGING_LEVELS == 2)
+ MiCheckPdeForPagedPool(Address);
+#endif
+ /* See if that fixed it */
+ if (PointerPte->u.Hard.Valid == 1) Status = STATUS_SUCCESS;
+
+ /* Return the status */
+ MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
+ return Status;
+ }
+
/* Did we get a prototype PTE back? */
if (!ProtoPte)
{
/* Lock the PFN database since we're going to grab a page */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Try to get a zero page */
+ 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);
- /* Grab a page out of there. Later we should grab a colored zero page */
- PageFrameIndex = MiRemoveAnyPage(0);
- ASSERT(PageFrameIndex);
-
- /* Release the lock since we need to do some zeroing */
- KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ /* 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);
+ /* 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);
+ /* Grab the lock again so we can initialize the PFN entry */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ }
/* Initialize the PFN entry now */
MiInitializePfn(PageFrameIndex, PointerPte, 1);