[NTOS]: When expanding paged pool, use MiRemoveAnyPage, not MmAllocPage.
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / pagfault.c
index e3b7401..8fd0d15 100644 (file)
@@ -24,9 +24,13 @@ NTSTATUS
 FASTCALL
 MiCheckPdeForPagedPool(IN PVOID Address)
 {
-    PMMPTE PointerPde;
+    PMMPDE PointerPde;
     NTSTATUS Status = STATUS_SUCCESS;
     
+    /* No session support in ReactOS yet */
+    ASSERT(MI_IS_SESSION_ADDRESS(Address) == FALSE);
+    ASSERT(MI_IS_SESSION_PTE(Address) == FALSE);
+    
     //
     // Check if this is a fault while trying to access the page table itself
     //
@@ -37,7 +41,7 @@ MiCheckPdeForPagedPool(IN PVOID Address)
         // Send a hint to the page fault handler that this is only a valid fault
         // if we already detected this was access within the page table range
         //
-        PointerPde = MiAddressToPte(Address);
+        PointerPde = (PMMPDE)MiAddressToPte(Address);
         Status = STATUS_WAIT_1;
     }
     else if (Address < MmSystemRangeStart)
@@ -60,6 +64,9 @@ MiCheckPdeForPagedPool(IN PVOID Address)
     //
     if (PointerPde->u.Hard.Valid == 0)
     {
+        /* This seems to be making the assumption that one PDE is one page long */
+        C_ASSERT(PAGE_SIZE == (PD_COUNT * (sizeof(MMPTE) * PDE_COUNT)));
+        
         //
         // Copy it from our double-mapped system page directory
         //
@@ -84,21 +91,26 @@ MiResolveDemandZeroFault(IN PVOID Address,
 {
     PFN_NUMBER PageFrameNumber;
     MMPTE TempPte;
-    DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n",
+    DPRINT1("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n",
             Address,
             Process);
     
+    /* Must currently only be called by paging path, for system addresses only */
+    ASSERT(OldIrql == MM_NOIRQL);
+    ASSERT(Process == NULL);
+        
     //
     // Lock the PFN database
     //
     OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
     ASSERT(PointerPte->u.Hard.Valid == 0);
     
-    //
-    // Get a page
-    //
-    PageFrameNumber = MmAllocPage(MC_PPOOL, 0);
-    DPRINT("New pool page: %lx\n", PageFrameNumber);
+    /* Get a page */
+    PageFrameNumber = MiRemoveAnyPage(0);
+    DPRINT1("New pool page: %lx\n", PageFrameNumber);
+    
+    /* Initialize it */
+    MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
     
     //
     // Release PFN lock
@@ -110,18 +122,20 @@ MiResolveDemandZeroFault(IN PVOID Address,
     //
     InterlockedIncrement(&KeGetCurrentPrcb()->MmDemandZeroCount);
     
-    //
-    // Build the PTE
-    //
-    TempPte = HyperTemplatePte;
-    TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
+    /* Shouldn't see faults for user PTEs yet */
+    ASSERT(PointerPte > MiHighestUserPte);
+    
+    /* Build the PTE */
+    MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, PointerPte->u.Soft.Protection, PageFrameNumber);
+    ASSERT(TempPte.u.Hard.Valid == 1);
+    ASSERT(PointerPte->u.Hard.Valid == 0);
     *PointerPte = TempPte;
     ASSERT(PointerPte->u.Hard.Valid == 1);
     
     //
     // It's all good now
     //
-    DPRINT("Paged pool page has now been paged in\n");
+    DPRINT1("Paged pool page has now been paged in\n");
     return STATUS_PAGE_FAULT_DEMAND_ZERO;
 }
 
@@ -140,8 +154,8 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
     KIRQL OldIrql;
     NTSTATUS Status;
     DPRINT("ARM3 Page Fault Dispatcher for address: %p in process: %p\n",
-            Address,
-            Process);
+             Address,
+             Process);
     
     //
     // Make sure APCs are off and we're not at dispatch
@@ -155,6 +169,9 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
     //
     TempPte = *PointerPte;
     
+    /* No prototype */
+    ASSERT(PrototypePte == NULL);
+    
     //
     // The PTE must be invalid, but not totally blank
     //
@@ -175,7 +192,8 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
     Status = MiResolveDemandZeroFault(Address,
                                       PointerPte,
                                       Process,
-                                      -1);
+                                      MM_NOIRQL);
+    ASSERT(KeAreAllApcsDisabled () == TRUE);
     if (NT_SUCCESS(Status))
     {
         //
@@ -200,7 +218,8 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
                  IN PVOID TrapInformation)
 {
     KIRQL OldIrql = KeGetCurrentIrql(), LockIrql;
-    PMMPTE PointerPde, PointerPte;
+    PMMPTE PointerPte;
+    PMMPDE PointerPde;
     MMPTE TempPte;
     PETHREAD CurrentThread;
     NTSTATUS Status;
@@ -297,14 +316,27 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
         
         //
         // Check for a fault on the page table or hyperspace itself
-        // FIXME: Use MmHyperSpaceEnd
         //
-        if ((Address >= (PVOID)PTE_BASE) && (Address <= (PVOID)0xC0800000))
+        if ((Address >= (PVOID)PTE_BASE) && (Address <= MmHyperSpaceEnd))
         {
             //
             // This might happen...not sure yet
             //
-            DPRINT1("FAULT ON PAGE TABLES!\n");
+            DPRINT1("FAULT ON PAGE TABLES: %p %lx %lx!\n", Address, *PointerPte, *PointerPde);
+            
+            //
+            // Map in the page table
+            //
+            if (MiCheckPdeForPagedPool(Address) == STATUS_WAIT_1)
+            {
+                DPRINT1("PAGE TABLES FAULTED IN!\n");
+                return STATUS_SUCCESS;
+            }
+            
+            //
+            // Otherwise the page table doesn't actually exist
+            //
+            DPRINT1("FAILING\n");
             return STATUS_ACCESS_VIOLATION;
         }