[NTOS/MM]
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / pagfault.c
index d8516bf..0236bbf 100644 (file)
@@ -1310,20 +1310,41 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
         }
     }
 
+    /* Is this a transition PTE */
+    if (TempPte.u.Soft.Transition)
+    {
+        PVOID InPageBlock = NULL;
+        /* Lock the PFN database */
+        LockIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+        /* Resolve */
+        Status = MiResolveTransitionFault(Address, PointerPte, Process, LockIrql, &InPageBlock);
+
+        NT_ASSERT(NT_SUCCESS(Status));
+
+        /* And now release the lock and leave*/
+        KeReleaseQueuedSpinLock(LockQueuePfnLock, LockIrql);
+
+        ASSERT(OldIrql == KeGetCurrentIrql());
+        ASSERT(OldIrql <= APC_LEVEL);
+        ASSERT(KeAreAllApcsDisabled() == TRUE);
+        return Status;
+    }
+
     //
     // The PTE must be invalid but not completely empty. It must also not be a
-    // prototype PTE as that scenario should've been handled above. These are
-    // all Windows checks
+    // prototype or transition PTE as those scenarii should've been handled above.
+    // These are all Windows checks
     //
     ASSERT(TempPte.u.Hard.Valid == 0);
     ASSERT(TempPte.u.Soft.Prototype == 0);
+    ASSERT(TempPte.u.Soft.Transition == 0);
     ASSERT(TempPte.u.Long != 0);
 
     //
-    // No transition or page file software PTEs in ARM3 yet, so this must be a
-    // demand zero page. These are all ReactOS checks
+    // No page file software PTEs in ARM3 yet, so this must be a
+    // demand zero page. This is a ReactOS check.
     //
-    ASSERT(TempPte.u.Soft.Transition == 0);
     ASSERT(TempPte.u.Soft.PageFileHigh == 0);
 
     //
@@ -1835,9 +1856,37 @@ UserFault:
         ASSERT(MI_IS_PAGE_LARGE(PointerPde) == FALSE);
     }
 
-    /* Now capture the PTE. Ignore virtual faults for now */
+    /* Now capture the PTE. */
     TempPte = *PointerPte;
-    ASSERT(TempPte.u.Hard.Valid == 0);
+
+    /* Check if the PTE is valid */
+    if (TempPte.u.Hard.Valid)
+    {
+        /* Check if this is a write on a readonly PTE */
+        if (StoreInstruction)
+        {
+            /* Is this a copy on write PTE? */
+            if (TempPte.u.Hard.CopyOnWrite)
+            {
+                /* Not supported yet */
+                ASSERT(FALSE);
+            }
+
+            /* Is this a read-only PTE? */
+            if (!TempPte.u.Hard.Write)
+            {
+                /* Return the status */
+                MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
+                return STATUS_ACCESS_VIOLATION;
+            }
+        }
+
+        /* FIXME: Execution is ignored for now, since we don't have no-execute pages yet */
+
+        /* The fault has already been resolved by a different thread */
+        MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
+        return STATUS_SUCCESS;
+    }
 
     /* Quick check for demand-zero */
     if (TempPte.u.Long == (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS))