[CMAKE]
[reactos.git] / ntoskrnl / mm / i386 / page.c
index 96a97d9..a7dbce4 100644 (file)
@@ -12,6 +12,7 @@
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <debug.h>
+#include "../ARM3/miarm.h"
 
 #if defined (ALLOC_PRAGMA)
 #pragma alloc_text(INIT, MmInitGlobalKernelPageDirectory)
@@ -58,6 +59,93 @@ __inline LARGE_INTEGER PTE_TO_PAGE(ULONG npage)
 }
 #endif
 
+const
+ULONG
+MmProtectToPteMask[32] =
+{
+    //
+    // These are the base MM_ protection flags
+    //
+    0,
+    PTE_READONLY            | PTE_ENABLE_CACHE,
+    PTE_EXECUTE             | PTE_ENABLE_CACHE,
+    PTE_EXECUTE_READ        | PTE_ENABLE_CACHE,
+    PTE_READWRITE           | PTE_ENABLE_CACHE,
+    PTE_WRITECOPY           | PTE_ENABLE_CACHE,
+    PTE_EXECUTE_READWRITE   | PTE_ENABLE_CACHE,
+    PTE_EXECUTE_WRITECOPY   | PTE_ENABLE_CACHE,
+    //
+    // These OR in the MM_NOCACHE flag
+    //
+    0,
+    PTE_READONLY            | PTE_DISABLE_CACHE,
+    PTE_EXECUTE             | PTE_DISABLE_CACHE,
+    PTE_EXECUTE_READ        | PTE_DISABLE_CACHE,
+    PTE_READWRITE           | PTE_DISABLE_CACHE,
+    PTE_WRITECOPY           | PTE_DISABLE_CACHE,
+    PTE_EXECUTE_READWRITE   | PTE_DISABLE_CACHE,
+    PTE_EXECUTE_WRITECOPY   | PTE_DISABLE_CACHE,
+    //
+    // These OR in the MM_DECOMMIT flag, which doesn't seem supported on x86/64/ARM
+    //
+    0,
+    PTE_READONLY            | PTE_ENABLE_CACHE,
+    PTE_EXECUTE             | PTE_ENABLE_CACHE,
+    PTE_EXECUTE_READ        | PTE_ENABLE_CACHE,
+    PTE_READWRITE           | PTE_ENABLE_CACHE,
+    PTE_WRITECOPY           | PTE_ENABLE_CACHE,
+    PTE_EXECUTE_READWRITE   | PTE_ENABLE_CACHE,
+    PTE_EXECUTE_WRITECOPY   | PTE_ENABLE_CACHE,
+    //
+    // These OR in the MM_NOACCESS flag, which seems to enable WriteCombining?
+    //
+    0,
+    PTE_READONLY            | PTE_WRITECOMBINED_CACHE,
+    PTE_EXECUTE             | PTE_WRITECOMBINED_CACHE,
+    PTE_EXECUTE_READ        | PTE_WRITECOMBINED_CACHE,
+    PTE_READWRITE           | PTE_WRITECOMBINED_CACHE,
+    PTE_WRITECOPY           | PTE_WRITECOMBINED_CACHE,
+    PTE_EXECUTE_READWRITE   | PTE_WRITECOMBINED_CACHE,
+    PTE_EXECUTE_WRITECOPY   | PTE_WRITECOMBINED_CACHE,
+};
+
+const
+ULONG MmProtectToValue[32] =
+{
+    PAGE_NOACCESS,
+    PAGE_READONLY,
+    PAGE_EXECUTE,
+    PAGE_EXECUTE_READ,
+    PAGE_READWRITE,
+    PAGE_WRITECOPY,
+    PAGE_EXECUTE_READWRITE,
+    PAGE_EXECUTE_WRITECOPY,
+    PAGE_NOACCESS,
+    PAGE_NOCACHE | PAGE_READONLY,
+    PAGE_NOCACHE | PAGE_EXECUTE,
+    PAGE_NOCACHE | PAGE_EXECUTE_READ,
+    PAGE_NOCACHE | PAGE_READWRITE,
+    PAGE_NOCACHE | PAGE_WRITECOPY,
+    PAGE_NOCACHE | PAGE_EXECUTE_READWRITE,
+    PAGE_NOCACHE | PAGE_EXECUTE_WRITECOPY,
+    PAGE_NOACCESS,
+    PAGE_GUARD | PAGE_READONLY,
+    PAGE_GUARD | PAGE_EXECUTE,
+    PAGE_GUARD | PAGE_EXECUTE_READ,
+    PAGE_GUARD | PAGE_READWRITE,
+    PAGE_GUARD | PAGE_WRITECOPY,
+    PAGE_GUARD | PAGE_EXECUTE_READWRITE,
+    PAGE_GUARD | PAGE_EXECUTE_WRITECOPY,
+    PAGE_NOACCESS,
+    PAGE_WRITECOMBINE | PAGE_READONLY,
+    PAGE_WRITECOMBINE | PAGE_EXECUTE,
+    PAGE_WRITECOMBINE | PAGE_EXECUTE_READ,
+    PAGE_WRITECOMBINE | PAGE_READWRITE,
+    PAGE_WRITECOMBINE | PAGE_WRITECOPY,
+    PAGE_WRITECOMBINE | PAGE_EXECUTE_READWRITE,
+    PAGE_WRITECOMBINE | PAGE_EXECUTE_WRITECOPY
+};
+
 /* FUNCTIONS ***************************************************************/
 
 BOOLEAN MmUnmapPageTable(PULONG Pt);
@@ -112,120 +200,12 @@ ProtectToPTE(ULONG flProtect)
     return(Attributes);
 }
 
-NTSTATUS
-NTAPI
-Mmi386ReleaseMmInfo(PEPROCESS Process)
-{
-    PUSHORT LdtDescriptor;
-    ULONG LdtBase;
-    PULONG PageDir;
-    ULONG i;
-    
-    DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process);
-    
-    LdtDescriptor = (PUSHORT) &Process->Pcb.LdtDescriptor;
-    LdtBase = LdtDescriptor[1] |
-    ((LdtDescriptor[2] & 0xff) << 16) |
-    ((LdtDescriptor[3] & ~0xff) << 16);
-    
-    DPRINT("LdtBase: %x\n", LdtBase);
-    
-    if (LdtBase)
-    {
-        ExFreePool((PVOID) LdtBase);
-    }
-    
-    PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]));
-    for (i = 0; i < ADDR_TO_PDE_OFFSET(MmSystemRangeStart); i++)
-    {
-        if (PageDir[i] != 0)
-        {
-            MiZeroPage(PTE_TO_PFN(PageDir[i]));
-            MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(PageDir[i]));
-        }
-    }
-    MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(PageDir[ADDR_TO_PDE_OFFSET(HYPERSPACE)]));
-    MmDeleteHyperspaceMapping(PageDir);
-    MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]));
-
-    Process->Pcb.DirectoryTableBase[0] = 0;
-    Process->Pcb.DirectoryTableBase[1] = 0;
-
-    DPRINT("Finished Mmi386ReleaseMmInfo()\n");
-    return(STATUS_SUCCESS);
-}
-
-NTSTATUS
-NTAPI
-MmInitializeHandBuiltProcess(IN PEPROCESS Process,
-                             IN PULONG DirectoryTableBase)
-{
-    /* Share the directory base with the idle process */
-    DirectoryTableBase[0] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[0];
-    DirectoryTableBase[1] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[1];
-
-    /* Initialize the Addresss Space */
-    KeInitializeGuardedMutex(&Process->AddressCreationLock);
-    Process->Vm.WorkingSetExpansionLinks.Flink = NULL;
-    ASSERT(Process->VadRoot.NumberGenericTableElements == 0);
-    Process->VadRoot.BalancedRoot.u1.Parent = &Process->VadRoot.BalancedRoot;
-
-    /* The process now has an address space */
-    Process->HasAddressSpace = TRUE;
-    return STATUS_SUCCESS;
-}
-
-BOOLEAN
-NTAPI
-MmCreateProcessAddressSpace(IN ULONG MinWs,
-                            IN PEPROCESS Process,
-                            IN PULONG DirectoryTableBase)
-{
-    NTSTATUS Status;
-    ULONG i, j;
-    PFN_TYPE Pfn[2];
-    PULONG PageDirectory;
-    
-    DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", MinWs, Process);
-    
-    for (i = 0; i < 2; i++)
-    {
-        Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn[i]);
-        if (!NT_SUCCESS(Status))
-        {
-            for (j = 0; j < i; j++)
-            {
-                MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn[j]);
-            }
-            
-            return FALSE;
-        }
-    }
-    
-    PageDirectory = MmCreateHyperspaceMapping(Pfn[0]);
-    
-    memcpy(PageDirectory + ADDR_TO_PDE_OFFSET(MmSystemRangeStart),
-           MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(MmSystemRangeStart),
-           (1024 - ADDR_TO_PDE_OFFSET(MmSystemRangeStart)) * sizeof(ULONG));
-    
-    DPRINT("Addr %x\n",ADDR_TO_PDE_OFFSET(PAGETABLE_MAP));
-    PageDirectory[ADDR_TO_PDE_OFFSET(PAGETABLE_MAP)] = PFN_TO_PTE(Pfn[0]) | PA_PRESENT | PA_READWRITE;
-    PageDirectory[ADDR_TO_PDE_OFFSET(HYPERSPACE)] = PFN_TO_PTE(Pfn[1]) | PA_PRESENT | PA_READWRITE;
-    
-    MmDeleteHyperspaceMapping(PageDirectory);
-    
-    DirectoryTableBase[0] = PFN_TO_PTE(Pfn[0]);
-    DirectoryTableBase[1] = 0;
-    DPRINT("Finished MmCopyMmInfo(): 0x%x\n", DirectoryTableBase[0]);
-    return TRUE;
-}
-
 static PULONG
 MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
 {
     ULONG PdeOffset = ADDR_TO_PDE_OFFSET(Address);
     NTSTATUS Status;
-    PFN_TYPE Pfn;
+    PFN_NUMBER Pfn;
     ULONG Entry;
     PULONG Pt, PageDir;
     
@@ -243,7 +223,10 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
                 MmDeleteHyperspaceMapping(PageDir);
                 return NULL;
             }
-            Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
+            MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY);
+            if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+            if (!Process) MI_SET_PROCESS2("Kernel Legacy");
+            Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn);
             if (!NT_SUCCESS(Status) || Pfn == 0)
             {
                 KeBugCheck(MEMORY_MANAGEMENT);
@@ -251,7 +234,7 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
             Entry = InterlockedCompareExchangePte(&PageDir[PdeOffset], PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
             if (Entry != 0)
             {
-                MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
+                MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
                 Pfn = PTE_TO_PFN(Entry);
             }
         }
@@ -278,6 +261,9 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
                 {
                     return NULL;
                 }
+                MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY);
+                if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+                if (!Process) MI_SET_PROCESS2("Kernel Legacy");
                 Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn);
                 if (!NT_SUCCESS(Status) || Pfn == 0)
                 {
@@ -300,7 +286,10 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
             {
                 return NULL;
             }
-            Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
+            MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY);
+            if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+            if (!Process) MI_SET_PROCESS2("Kernel Legacy");
+            Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn);
             if (!NT_SUCCESS(Status) || Pfn == 0)
             {
                 KeBugCheck(MEMORY_MANAGEMENT);
@@ -308,7 +297,7 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
             Entry = InterlockedCompareExchangePte(PageDir, PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
             if (Entry != 0)
             {
-                MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
+                MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
             }
         }
     }
@@ -344,7 +333,7 @@ static ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
     return 0;
 }
 
-PFN_TYPE
+PFN_NUMBER
 NTAPI
 MmGetPfnForProcess(PEPROCESS Process,
                    PVOID Address)
@@ -360,7 +349,7 @@ MmGetPfnForProcess(PEPROCESS Process,
 
 VOID
 NTAPI
-MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN* WasDirty, PPFN_TYPE Page)
+MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN* WasDirty, PPFN_NUMBER Page)
 /*
  * FUNCTION: Delete a virtual mapping
  */
@@ -422,13 +411,13 @@ MmRawDeleteVirtualMapping(PVOID Address)
 VOID
 NTAPI
 MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
-                       BOOLEAN* WasDirty, PPFN_TYPE Page)
+                       BOOLEAN* WasDirty, PPFN_NUMBER Page)
 /*
  * FUNCTION: Delete a virtual mapping
  */
 {
     BOOLEAN WasValid = FALSE;
-    PFN_TYPE Pfn;
+    PFN_NUMBER Pfn;
     ULONG Pte;
     PULONG Pt;
     
@@ -469,7 +458,7 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
     
     if (FreePage && WasValid)
     {
-        MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
+        MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
     }
     
     /*
@@ -485,6 +474,18 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
     }
 }
 
+VOID
+NTAPI
+MmGetPageFileMapping(PEPROCESS Process, PVOID Address,
+                                        SWAPENTRY* SwapEntry)
+/*
+ * FUNCTION: Get a page file mapping
+ */
+{
+       ULONG Entry = MmGetPageEntryForProcess(Process, Address);
+       *SwapEntry = Entry >> 1;
+}
+
 VOID
 NTAPI
 MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
@@ -701,7 +702,7 @@ NTAPI
 MmCreateVirtualMappingUnsafe(PEPROCESS Process,
                              PVOID Address,
                              ULONG flProtect,
-                             PPFN_TYPE Pages,
+                             PPFN_NUMBER Pages,
                              ULONG PageCount)
 {
     ULONG Attributes;
@@ -710,8 +711,6 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
     ULONG oldPdeOffset, PdeOffset;
     PULONG Pt = NULL;
     ULONG Pte;
-    BOOLEAN NoExecute = FALSE;
-    
     DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x (%x), %d)\n",
            Process, Address, flProtect, Pages, *Pages, PageCount);
     
@@ -746,10 +745,6 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
     }
     
     Attributes = ProtectToPTE(flProtect);
-    if (Attributes & 0x80000000)
-    {
-        NoExecute = TRUE;
-    }
     Attributes &= 0xfff;
     if (Address >= MmSystemRangeStart)
     {
@@ -816,7 +811,7 @@ NTAPI
 MmCreateVirtualMapping(PEPROCESS Process,
                        PVOID Address,
                        ULONG flProtect,
-                       PPFN_TYPE Pages,
+                       PPFN_NUMBER Pages,
                        ULONG PageCount)
 {
     ULONG i;
@@ -883,7 +878,6 @@ NTAPI
 MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
 {
     ULONG Attributes = 0;
-    BOOLEAN NoExecute = FALSE;
     PULONG Pt;
     
     DPRINT("MmSetPageProtect(Process %x  Address %x  flProtect %x)\n",
@@ -891,10 +885,6 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
     
     Attributes = ProtectToPTE(flProtect);
 
-    if (Attributes & 0x80000000)
-    {
-        NoExecute = TRUE;
-    }
     Attributes &= 0xfff;
     if (Address >= MmSystemRangeStart)
     {
@@ -940,54 +930,6 @@ MmGetPhysicalAddress(PVOID vaddr)
     return p;
 }
 
-VOID
-NTAPI
-MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size)
-{
-    ULONG StartOffset, EndOffset, Offset;
-    PULONG Pde;
-    
-    //
-    // Check if the process isn't there anymore
-    // This is probably a bad sign, since it means the caller is setting cr3 to
-    // 0 or something...
-    //
-    if ((PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]) == 0) && (Process != PsGetCurrentProcess()))
-    {
-        DPRINT1("Process: %16s is dead: %p\n", Process->ImageFileName, Process->Pcb.DirectoryTableBase[0]);
-        ASSERT(FALSE);
-        return;
-    }
-
-    if (Address < MmSystemRangeStart)
-    {
-        KeBugCheck(MEMORY_MANAGEMENT);
-    }
-
-    StartOffset = ADDR_TO_PDE_OFFSET(Address);
-    EndOffset = ADDR_TO_PDE_OFFSET((PVOID)((ULONG_PTR)Address + Size));
-
-    if (Process != NULL && Process != PsGetCurrentProcess())
-    {
-        Pde = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]));
-    }
-    else
-    {
-        Pde = (PULONG)PAGEDIRECTORY_MAP;
-    }
-    for (Offset = StartOffset; Offset <= EndOffset; Offset++)
-    {
-        if (Offset != ADDR_TO_PDE_OFFSET(PAGETABLE_MAP))
-        {
-            InterlockedCompareExchangePte(&Pde[Offset], MmGlobalKernelPageDirectory[Offset], 0);
-        }
-    }
-    if (Pde != (PULONG)PAGEDIRECTORY_MAP)
-    {
-        MmDeleteHyperspaceMapping(Pde);
-    }
-}
-
 VOID
 INIT_FUNCTION
 NTAPI