Merge 36852, 37322, 37333, 37334, 43428, 43451, 44259, 46404 from amd64 branch.
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / virtual.c
index 88ff54f..fd7f0e1 100644 (file)
@@ -29,6 +29,114 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
+PFN_NUMBER
+NTAPI
+MiDeleteSystemPageableVm(IN PMMPTE PointerPte,
+                         IN PFN_NUMBER PageCount,
+                         IN ULONG Flags,
+                         OUT PPFN_NUMBER ValidPages)
+{                     
+    PFN_NUMBER ActualPages = 0;
+    PETHREAD CurrentThread;
+    PMMPFN Pfn1, Pfn2;
+    PFN_NUMBER PageFrameIndex, PageTableIndex;
+    KIRQL OldIrql, LockIrql;
+    ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
+    
+    /*
+     * Now we must raise to APC_LEVEL and mark the thread as owner
+     * We don't actually implement a working set pushlock, so this is only
+     * for internal consistency (and blocking APCs)
+     */
+    KeRaiseIrql(APC_LEVEL, &LockIrql);
+    CurrentThread = PsGetCurrentThread();
+    KeEnterGuardedRegion();
+    ASSERT((CurrentThread->OwnsSystemWorkingSetExclusive == 0) &&
+           (CurrentThread->OwnsSystemWorkingSetShared == 0));
+    CurrentThread->OwnsSystemWorkingSetExclusive = 1;
+                
+    /* Loop all pages */
+    while (PageCount)
+    {
+        /* Make sure there's some data about the page */
+        if (PointerPte->u.Long)
+        {
+            /* As always, only handle current ARM3 scenarios */
+            ASSERT(PointerPte->u.Soft.Prototype == 0);
+            ASSERT(PointerPte->u.Soft.Transition == 0);
+            
+            /* Normally this is one possibility -- freeing a valid page */
+            if (PointerPte->u.Hard.Valid)
+            {
+                /* Get the page PFN */
+                PageFrameIndex = PFN_FROM_PTE(PointerPte);
+                Pfn1 = MiGetPfnEntry(PageFrameIndex);
+                
+                /* Should not have any working set data yet */
+                ASSERT(Pfn1->u1.WsIndex == 0);
+                
+                /* Actual valid, legitimate, pages */
+                if (ValidPages) *ValidPages++;
+                
+                /* Get the page table entry */
+                PageTableIndex = Pfn1->u4.PteFrame;
+                Pfn2 = MiGetPfnEntry(PageTableIndex);
+                
+                /* Lock the PFN database */
+                OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+                
+                /* Delete it the page */
+                MI_SET_PFN_DELETED(Pfn1);
+                MiDecrementShareCount(Pfn1, PageFrameIndex);
+                
+                /* Decrement the page table too */
+                #if 0 // ARM3: Dont't trust this yet
+                MiDecrementShareCount(Pfn2, PageTableIndex);
+                #endif
+                
+                /* Release the PFN database */
+                KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+                
+                /* Destroy the PTE */
+                PointerPte->u.Long = 0;
+            }
+    
+            /* Actual legitimate pages */
+            ActualPages++;
+        }
+        else
+        {
+            /* 
+             * The only other ARM3 possibility is a demand zero page, which would
+             * mean freeing some of the paged pool pages that haven't even been
+             * touched yet, as part of a larger allocation.
+             *
+             * Right now, we shouldn't expect any page file information in the PTE
+             */
+             ASSERT(PointerPte->u.Soft.PageFileHigh == 0);
+             
+            /* Destroy the PTE */
+            PointerPte->u.Long = 0;
+        }
+        
+        /* Keep going */
+        PointerPte++;
+        PageCount--;
+    }
+    
+    /* Re-enable APCs */
+    ASSERT(KeAreAllApcsDisabled() == TRUE);
+    CurrentThread->OwnsSystemWorkingSetExclusive = 0;
+    KeLeaveGuardedRegion();
+    KeLowerIrql(LockIrql);
+    
+    /* Flush the entire TLB */
+    KeFlushEntireTb(TRUE, TRUE);
+    
+    /* Done */
+    return ActualPages;
+}
+
 LONG
 MiGetExceptionInfo(IN PEXCEPTION_POINTERS ExceptionInfo,
                    OUT PBOOLEAN HaveBadAddress, 
@@ -634,7 +742,7 @@ MmSecureVirtualMemory(IN PVOID Address,
                       IN SIZE_T Length,
                       IN ULONG Mode)
 {
-    UNIMPLEMENTED;
+    static BOOLEAN Warn; if (!Warn++) UNIMPLEMENTED;
     return Address;
 }
 
@@ -645,7 +753,7 @@ VOID
 NTAPI
 MmUnsecureVirtualMemory(IN PVOID SecureMem)
 {
-    UNIMPLEMENTED;
+    static BOOLEAN Warn; if (!Warn++) UNIMPLEMENTED;
 }
 
 /* SYSTEM CALLS ***************************************************************/
@@ -775,7 +883,7 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle,
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
     PEPROCESS Process;
     NTSTATUS Status = STATUS_SUCCESS;
-    ULONG BytesWritten = 0;
+    SIZE_T BytesWritten = 0;
     PAGED_CODE();
 
     //