Author: sir_richard
Date: Thu Oct 7 17:27:23 2010
New Revision: 49035
URL:
http://svn.reactos.org/svn/reactos?rev=49035&view=rev
Log:
[NTOS]: Add support for user-mode VAD faults on page tables (just a couple lines of extra
code).
[NTOS]: Add support for user-mode VAD demand zero faults.
[NTOS]: Remove broken ASSERT.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pagfault.…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Thu Oct 7 17:27:23 2010
@@ -32,8 +32,25 @@
/* No prototype/section support for now */
*ProtoVad = NULL;
- /* Only valid for user VADs for now */
- ASSERT(VirtualAddress <= MM_HIGHEST_USER_ADDRESS);
+ /* Check if this is a page table address */
+ if (MI_IS_PAGE_TABLE_ADDRESS(VirtualAddress))
+ {
+ /* This should never happen, as these addresses are handled by the double-maping
*/
+ if (((PMMPTE)VirtualAddress >= MiAddressToPte(MmPagedPoolStart)) &&
+ ((PMMPTE)VirtualAddress <= MmPagedPoolInfo.LastPteForPagedPool))
+ {
+ /* Fail such access */
+ *ProtectCode = MM_NOACCESS;
+ return NULL;
+ }
+
+ /* Return full access rights */
+ *ProtectCode = MM_READWRITE;
+ return NULL;
+ }
+
+ /* Should not be a session address */
+ ASSERT(MI_IS_SESSION_ADDRESS(VirtualAddress) == FALSE);
/* Special case for shared data */
if (PAGE_ALIGN(VirtualAddress) == (PVOID)USER_SHARED_DATA)
@@ -642,7 +659,7 @@
//
// Check for kernel fault
//
- if (Address >= MmSystemRangeStart)
+ while (Address >= MmSystemRangeStart)
{
//
// What are you even DOING here?
@@ -718,25 +735,16 @@
//
if (MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address))
{
- //
- // 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
- //
+ /* Could be paged pool access from a new process -- synchronize the page
directories */
if (MiCheckPdeForPagedPool(Address) == STATUS_WAIT_1)
{
DPRINT1("PAGE TABLES FAULTED IN!\n");
return STATUS_SUCCESS;
}
#endif
- //
- // Otherwise the page table doesn't actually exist
- //
- DPRINT1("FAILING\n");
- return STATUS_ACCESS_VIOLATION;
+ /* Otherwise this could be a commit of a virtual address */
+ break;
}
/* In this path, we are using the system working set */
@@ -866,7 +874,8 @@
#endif
/* First things first, is the PDE valid? */
- ASSERT(PointerPde != MiAddressToPde(PTE_BASE));
+// DPRINT1("The PDE we faulted on: %lx %lx\n", PointerPde,
MiAddressToPde(PTE_BASE));
+ //ASSERT(PointerPde != MiAddressToPde(PTE_BASE));
ASSERT(PointerPde->u.Hard.LargePage == 0);
if (PointerPde->u.Hard.Valid == 0)
{
@@ -901,8 +910,27 @@
ASSERT(PointerPde->u.Hard.Valid == 1);
}
- /* Now capture the PTE. We only handle cases where it's totally empty */
+ /* Now capture the PTE. Ignore virtual faults for now */
TempPte = *PointerPte;
+ ASSERT(TempPte.u.Hard.Valid == 0);
+
+ /* Quick check for demand-zero */
+ if (TempPte.u.Long == (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS))
+ {
+ /* Resolve the fault */
+ //DPRINT1("VAD demand-zero fault: %p\n", Address);
+ MiResolveDemandZeroFault(Address,
+ PointerPte,
+ CurrentProcess,
+ MM_NOIRQL);
+
+ /* Return the status */
+ MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
+ return STATUS_PAGE_FAULT_DEMAND_ZERO;
+ }
+
+ /* Don't handle prototype PTEs yet -- only kernel demand zero PTEs */
+ ASSERT(TempPte.u.Soft.Prototype == 0);
ASSERT(TempPte.u.Long == 0);
/* Check if this address range belongs to a valid allocation (VAD) */