[NTOS] Deduplicate MiSynchronizeSystemPde(). #179
[reactos.git] / ntoskrnl / mm / i386 / page.c
index 9ebf1bd..4ed0ebc 100644 (file)
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <debug.h>
-#include "../ARM3/miarm.h"
+#include <mm/ARM3/miarm.h>
 
 #if defined (ALLOC_PRAGMA)
 #pragma alloc_text(INIT, MmInitGlobalKernelPageDirectory)
-#pragma alloc_text(INIT, MiInitPageDirectoryMap)
 #endif
 
+#define ADDR_TO_PDE_OFFSET MiAddressToPdeOffset
+#define ADDR_TO_PAGE_TABLE(v)  (((ULONG)(v)) / (1024 * PAGE_SIZE))
 
 /* GLOBALS *****************************************************************/
 
 #define PA_ACCESSED  (1 << PA_BIT_ACCESSED)
 #define PA_GLOBAL    (1 << PA_BIT_GLOBAL)
 
-#define HYPERSPACE          (0xc0400000)
-#define IS_HYPERSPACE(v)    (((ULONG)(v) >= HYPERSPACE && (ULONG)(v) < HYPERSPACE + 0x400000))
-
-ULONG MmGlobalKernelPageDirectory[1024];
+#define IS_HYPERSPACE(v)    (((ULONG)(v) >= HYPER_SPACE && (ULONG)(v) <= HYPER_SPACE_END))
 
 #define PTE_TO_PFN(X)  ((X) >> PAGE_SHIFT)
 #define PFN_TO_PTE(X)  ((X) << PAGE_SHIFT)
 
-#if defined(__GNUC__)
-#define PTE_TO_PAGE(X) ((LARGE_INTEGER)(LONGLONG)(PAGE_MASK(X)))
-#else
-__inline LARGE_INTEGER PTE_TO_PAGE(ULONG npage)
-{
-    LARGE_INTEGER dummy;
-    dummy.QuadPart = (LONGLONG)(PAGE_MASK(npage));
-    return dummy;
-}
-#endif
+#define PAGE_MASK(x)           ((x)&(~0xfff))
 
 const
 ULONG
@@ -148,7 +137,7 @@ ULONG MmProtectToValue[32] =
 
 /* FUNCTIONS ***************************************************************/
 
-BOOLEAN MmUnmapPageTable(PULONG Pt);
+static BOOLEAN MmUnmapPageTable(PULONG Pt);
 
 VOID
 MiFlushTlb(PULONG Pt, PVOID Address)
@@ -200,72 +189,28 @@ ProtectToPTE(ULONG flProtect)
     return(Attributes);
 }
 
-static
-VOID
-MmDeletePageDirectoryEntry(ULONG PdeEntry)
-{
-    KIRQL OldIrql;
-    PMMPFN Page;
-
-    Page = MiGetPfnEntry(PTE_TO_PFN(PdeEntry));
-
-    /* Check if this is a legacy allocation */
-    if (MI_IS_ROS_PFN(Page))
-    {
-        /* Free it using the legacy API */
-        MmReleasePageMemoryConsumer(MC_SYSTEM, PTE_TO_PFN(PdeEntry));
-    }
-    else
-    {
-        OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-
-        /* Free it using the ARM3 API */
-        MI_SET_PFN_DELETED(Page);
-        MiDecrementShareCount(Page, PTE_TO_PFN(PdeEntry));
-
-        KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
-    }
-}
-
-VOID
+NTSTATUS
 NTAPI
-MmDeleteProcessPageDirectory(PEPROCESS Process)
-{
-    PULONG PageDir;
-    ULONG PdeOffset;
+MiDispatchFault(IN BOOLEAN StoreInstruction,
+                IN PVOID Address,
+                IN PMMPTE PointerPte,
+                IN PMMPTE PointerProtoPte,
+                IN BOOLEAN Recursive,
+                IN PEPROCESS Process,
+                IN PVOID TrapInformation,
+                IN PVOID Vad);
 
-    /* Map the page directory in hyperspace */
-    PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]));
-
-    /* Loop the user land page directory */
-    for (PdeOffset = 0; PdeOffset < ADDR_TO_PDE_OFFSET(MmSystemRangeStart); PdeOffset++)
-    {
-        /* Check if a valid PDE exists here */
-        if (PageDir[PdeOffset] != 0)
-        {
-            /* Free the page that backs it */
-            MmDeletePageDirectoryEntry(PageDir[PdeOffset]);
-        }
-    }
-
-    /* Free the hyperspace mapping page (ARM3) */
-    MmDeletePageDirectoryEntry(PageDir[ADDR_TO_PDE_OFFSET(HYPERSPACE)]);
-
-    /* Delete the hyperspace mapping */
-    MmDeleteHyperspaceMapping(PageDir);
-
-    /* Free the PDE page itself (ARM3) */
-    MmDeletePageDirectoryEntry(Process->Pcb.DirectoryTableBase[0]);
-}
+NTSTATUS
+NTAPI
+MiFillSystemPageDirectory(IN PVOID Base,
+                          IN SIZE_T NumberOfBytes);
 
 static PULONG
 MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
 {
-    ULONG PdeOffset = ADDR_TO_PDE_OFFSET(Address);
-    NTSTATUS Status;
     PFN_NUMBER Pfn;
-    ULONG Entry;
-    PULONG Pt, PageDir;
+    PULONG Pt;
+    PMMPDE PointerPde;
 
     if (Address < MmSystemRangeStart)
     {
@@ -274,39 +219,29 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
 
         if(Process != PsGetCurrentProcess())
         {
-            PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]));
-            if (PageDir == NULL)
+            PMMPDE PdeBase;
+            ULONG PdeOffset = MiGetPdeOffset(Address);
+
+            /* Nobody but page fault should ask for creating the PDE,
+             * Which imples that Process is the current one */
+            ASSERT(Create == FALSE);
+
+            PdeBase = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]));
+            if (PdeBase == NULL)
             {
                 KeBugCheck(MEMORY_MANAGEMENT);
             }
-            if (0 == InterlockedCompareExchangePte(&PageDir[PdeOffset], 0, 0))
+            PointerPde = PdeBase + PdeOffset;
+            if (PointerPde->u.Hard.Valid == 0)
             {
-                if (Create == FALSE)
-                {
-                    MmDeleteHyperspaceMapping(PageDir);
-                    return NULL;
-                }
-                MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY);
-
-                MI_SET_PROCESS2(Process->ImageFileName);
-
-                Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn);
-                if (!NT_SUCCESS(Status) || Pfn == 0)
-                {
-                    KeBugCheck(MEMORY_MANAGEMENT);
-                }
-                Entry = InterlockedCompareExchangePte(&PageDir[PdeOffset], PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
-                if (Entry != 0)
-                {
-                    MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
-                    Pfn = PTE_TO_PFN(Entry);
-                }
+                MmDeleteHyperspaceMapping(PdeBase);
+                return NULL;
             }
             else
             {
-                Pfn = PTE_TO_PFN(PageDir[PdeOffset]);
+                Pfn = PointerPde->u.Hard.PageFrameNumber;
             }
-            MmDeleteHyperspaceMapping(PageDir);
+            MmDeleteHyperspaceMapping(PdeBase);
             Pt = MmCreateHyperspaceMapping(Pfn);
             if (Pt == NULL)
             {
@@ -315,62 +250,52 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
             return Pt + MiAddressToPteOffset(Address);
         }
         /* This is for our process */
-        PageDir = (PULONG)MiAddressToPde(Address);
-        if (0 == InterlockedCompareExchangePte(PageDir, 0, 0))
+        PointerPde = MiAddressToPde(Address);
+        Pt = (PULONG)MiAddressToPte(Address);
+        if (PointerPde->u.Hard.Valid == 0)
         {
+            NTSTATUS Status;
             if (Create == FALSE)
             {
                 return NULL;
             }
-            MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY);
-            MI_SET_PROCESS2(Process->ImageFileName);
-
-            Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn);
-            if (!NT_SUCCESS(Status) || Pfn == 0)
-            {
-                KeBugCheck(MEMORY_MANAGEMENT);
-            }
-            Entry = InterlockedCompareExchangePte(PageDir, PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
-            if (Entry != 0)
-            {
-                MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
-            }
+            ASSERT(PointerPde->u.Long == 0);
+
+            MI_WRITE_INVALID_PTE(PointerPde, DemandZeroPde);
+            Status = MiDispatchFault(TRUE,
+                                     Pt,
+                                     PointerPde,
+                                     NULL,
+                                     FALSE,
+                                     PsGetCurrentProcess(),
+                                     NULL,
+                                     NULL);
+            DBG_UNREFERENCED_LOCAL_VARIABLE(Status);
+            ASSERT(KeAreAllApcsDisabled() == TRUE);
+            ASSERT(PointerPde->u.Hard.Valid == 1);
         }
         return (PULONG)MiAddressToPte(Address);
     }
 
     /* This is for kernel land address */
-    PageDir = (PULONG)MiAddressToPde(Address);
-    if (0 == InterlockedCompareExchangePte(PageDir, 0, 0))
+    ASSERT(Process == NULL);
+    PointerPde = MiAddressToPde(Address);
+    Pt = (PULONG)MiAddressToPte(Address);
+    if (PointerPde->u.Hard.Valid == 0)
     {
-        if (0 == InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory[PdeOffset], 0, 0))
+        /* Let ARM3 synchronize the PDE */
+        if(!MiSynchronizeSystemPde(PointerPde))
         {
-            if (Create == FALSE)
-            {
+            /* PDE (still) not valid, let ARM3 allocate one if asked */
+            if(Create == FALSE)
                 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)
-            {
-                KeBugCheck(MEMORY_MANAGEMENT);
-            }
-            Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE;
-            if(0 != InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory[PdeOffset], Entry, 0))
-            {
-                MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
-            }
-            InterlockedExchangePte(PageDir, MmGlobalKernelPageDirectory[PdeOffset]);
-            return (PULONG)MiAddressToPte(Address);
+            MiFillSystemPageDirectory(Address, PAGE_SIZE);
         }
-        InterlockedExchangePte(PageDir, MmGlobalKernelPageDirectory[PdeOffset]);
     }
-    return (PULONG)MiAddressToPte(Address);
+    return Pt;
 }
 
-BOOLEAN MmUnmapPageTable(PULONG Pt)
+static BOOLEAN MmUnmapPageTable(PULONG Pt)
 {
     if (!IS_HYPERSPACE(Pt))
     {
@@ -415,70 +340,7 @@ MmGetPfnForProcess(PEPROCESS Process,
 
 VOID
 NTAPI
-MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN* WasDirty, PPFN_NUMBER Page)
-/*
- * FUNCTION: Delete a virtual mapping
- */
-{
-    BOOLEAN WasValid;
-    ULONG Pte;
-    PULONG Pt;
-
-    Pt = MmGetPageTableForProcess(Process, Address, FALSE);
-    if (Pt == NULL)
-    {
-        KeBugCheck(MEMORY_MANAGEMENT);
-    }
-
-    /*
-     * Atomically disable the present bit and get the old value.
-     */
-    do
-    {
-        Pte = *Pt;
-    } while (Pte != InterlockedCompareExchangePte(Pt, Pte & ~PA_PRESENT, Pte));
-
-    MiFlushTlb(Pt, Address);
-
-    WasValid = (Pte & PA_PRESENT);
-    if (!WasValid)
-    {
-        KeBugCheck(MEMORY_MANAGEMENT);
-    }
-
-    /*
-     * Return some information to the caller
-     */
-    if (WasDirty != NULL)
-    {
-        *WasDirty = Pte & PA_DIRTY;
-    }
-    if (Page != NULL)
-    {
-        *Page = PTE_TO_PFN(Pte);
-    }
-}
-
-VOID
-NTAPI
-MmRawDeleteVirtualMapping(PVOID Address)
-{
-    PULONG Pt;
-
-    Pt = MmGetPageTableForProcess(NULL, Address, FALSE);
-    if (Pt && *Pt)
-    {
-        /*
-         * Set the entry to zero
-         */
-        InterlockedExchangePte(Pt, 0);
-        MiFlushTlb(Pt, Address);
-    }
-}
-
-VOID
-NTAPI
-MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
+MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address,
                        BOOLEAN* WasDirty, PPFN_NUMBER Page)
 /*
  * FUNCTION: Delete a virtual mapping
@@ -489,8 +351,8 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
     ULONG Pte;
     PULONG Pt;
 
-    DPRINT("MmDeleteVirtualMapping(%x, %x, %d, %x, %x)\n",
-           Process, Address, FreePage, WasDirty, Page);
+    DPRINT("MmDeleteVirtualMapping(%p, %p, %p, %p)\n",
+           Process, Address, WasDirty, Page);
 
     Pt = MmGetPageTableForProcess(Process, Address, FALSE);
 
@@ -512,7 +374,9 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
      */
     Pte = InterlockedExchangePte(Pt, 0);
 
-    WasValid = (Pte & PA_PRESENT);
+    /* We count a mapping as valid if it's a present page, or it's a nonzero pfn with
+     * the swap bit unset, indicating a valid page protected to PAGE_NOACCESS. */
+    WasValid = (Pte & PA_PRESENT) || ((Pte >> PAGE_SHIFT) && !(Pte & 0x800));
     if (WasValid)
     {
         /* Flush the TLB since we transitioned this PTE
@@ -520,13 +384,14 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
          * are removed from the cache */
         MiFlushTlb(Pt, Address);
 
-        Pfn = PTE_TO_PFN(Pte);
+               if (Address < MmSystemRangeStart)
+               {
+                       /* Remove PDE reference */
+                       Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+                       ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_COUNT);
+               }
 
-        if (FreePage)
-        {
-            MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
-            Pfn = 0;
-        }
+        Pfn = PTE_TO_PFN(Pte);
     }
     else
     {
@@ -583,12 +448,20 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
      */
     Pte = InterlockedExchangePte(Pt, 0);
 
+       if (Address < MmSystemRangeStart)
+       {
+               /* Remove PDE reference */
+               Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+               ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_COUNT);
+       }
+
     /* We don't need to flush here because page file entries
      * are invalid translations, so the processor won't cache them */
     MmUnmapPageTable(Pt);
 
     if ((Pte & PA_PRESENT) || !(Pte & 0x800))
     {
+        DPRINT1("Pte %x (want not 1 and 0x800)\n", Pte);
         KeBugCheck(MEMORY_MANAGEMENT);
     }
 
@@ -599,19 +472,18 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
 }
 
 BOOLEAN
-Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
+Mmi386MakeKernelPageTableGlobal(PVOID Address)
 {
-    PULONG Pt, Pde;
-    Pde = (PULONG)MiAddressToPde(PAddress);
-    if (*Pde == 0)
+    PMMPDE PointerPde = MiAddressToPde(Address);
+    PMMPTE PointerPte = MiAddressToPte(Address);
+
+    if (PointerPde->u.Hard.Valid == 0)
     {
-        Pt = MmGetPageTableForProcess(NULL, PAddress, FALSE);
-        if (Pt != NULL)
-        {
-            return TRUE;
-        }
+        if(!MiSynchronizeSystemPde(PointerPde))
+            return FALSE;
+        return PointerPte->u.Hard.Valid != 0;
     }
-    return(FALSE);
+    return FALSE;
 }
 
 BOOLEAN
@@ -695,40 +567,19 @@ MmSetDirtyPage(PEPROCESS Process, PVOID Address)
     }
 }
 
-VOID
+BOOLEAN
 NTAPI
-MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
+MmIsPagePresent(PEPROCESS Process, PVOID Address)
 {
-    PULONG Pt;
-    ULONG Pte;
-
-    Pt = MmGetPageTableForProcess(Process, Address, FALSE);
-    if (Pt == NULL)
-    {
-        //HACK to get DPH working, waiting for MM rewrite :-/
-        //KeBugCheck(MEMORY_MANAGEMENT);
-        return;
-    }
-
-    /* Do not mark a 0 page as present */
-    if(0 == InterlockedCompareExchangePte(Pt, 0, 0))
-        return;
-
-    do
-    {
-        Pte = *Pt;
-    } while (Pte != InterlockedCompareExchangePte(Pt, Pte | PA_PRESENT, Pte));
-
-    /* We don't need to flush the TLB here because it
-     * won't cache translations for non-present pages */
-    MmUnmapPageTable(Pt);
+    return MmGetPageEntryForProcess(Process, Address) & PA_PRESENT;
 }
 
 BOOLEAN
 NTAPI
-MmIsPagePresent(PEPROCESS Process, PVOID Address)
+MmIsDisabledPage(PEPROCESS Process, PVOID Address)
 {
-    return MmGetPageEntryForProcess(Process, Address) & PA_PRESENT;
+    ULONG_PTR Entry = MmGetPageEntryForProcess(Process, Address);
+    return !(Entry & PA_PRESENT) && !(Entry & 0x800) && (Entry >> PAGE_SHIFT);
 }
 
 BOOLEAN
@@ -765,17 +616,30 @@ MmCreatePageFileMapping(PEPROCESS Process,
         KeBugCheck(MEMORY_MANAGEMENT);
     }
 
-    Pt = MmGetPageTableForProcess(Process, Address, TRUE);
+    Pt = MmGetPageTableForProcess(Process, Address, FALSE);
     if (Pt == NULL)
     {
-        KeBugCheck(MEMORY_MANAGEMENT);
+        /* Nobody should page out an address that hasn't even been mapped */
+        /* But we might place a wait entry first, requiring the page table */
+        if (SwapEntry != MM_WAIT_ENTRY)
+        {
+            KeBugCheck(MEMORY_MANAGEMENT);
+        }
+        Pt = MmGetPageTableForProcess(Process, Address, TRUE);
     }
     Pte = InterlockedExchangePte(Pt, SwapEntry << 1);
     if (Pte != 0)
     {
-        KeBugCheck(MEMORY_MANAGEMENT);
+        KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
     }
 
+       if (Address < MmSystemRangeStart)
+       {
+               /* Add PDE reference */
+               Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
+               ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT);
+       }
+
     /* We don't need to flush the TLB here because it
      * only caches valid translations and a zero PTE
      * is not a valid translation */
@@ -799,7 +663,7 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
     ULONG oldPdeOffset, PdeOffset;
     PULONG Pt = NULL;
     ULONG Pte;
-    DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x (%x), %d)\n",
+    DPRINT("MmCreateVirtualMappingUnsafe(%p, %p, %lu, %p (%x), %lu)\n",
            Process, Address, flProtect, Pages, *Pages, PageCount);
 
     ASSERT(((ULONG_PTR)Address % PAGE_SIZE) == 0);
@@ -854,7 +718,7 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
         if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
         {
             DPRINT1("Setting physical address but not allowing access at address "
-                    "0x%.8X with attributes %x/%x.\n",
+                    "0x%p with attributes %x/%x.\n",
                     Addr, Attributes, flProtect);
             KeBugCheck(MEMORY_MANAGEMENT);
         }
@@ -879,12 +743,19 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
         /* There should not be anything valid here */
         if (Pte != 0)
         {
-            DPRINT1("Bad PTE %lx\n", Pte);
+            DPRINT1("Bad PTE %lx at %p for %p + %lu\n", Pte, Pt, Address, i);
             KeBugCheck(MEMORY_MANAGEMENT);
         }
 
         /* We don't need to flush the TLB here because it only caches valid translations
          * and we're moving this PTE from invalid to valid so it can't be cached right now */
+
+               if (Addr < MmSystemRangeStart)
+               {
+                       /* Add PDE reference */
+                       Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Addr)]++;
+                       ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Addr)] <= PTE_COUNT);
+               }
     }
 
     ASSERT(Addr > Address);
@@ -903,6 +774,7 @@ MmCreateVirtualMapping(PEPROCESS Process,
 {
     ULONG i;
 
+    ASSERT((ULONG_PTR)Address % PAGE_SIZE == 0);
     for (i = 0; i < PageCount; i++)
     {
         if (!MmIsPageInUse(Pages[i]))
@@ -968,7 +840,7 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
     PULONG Pt;
     ULONG Pte;
 
-    DPRINT("MmSetPageProtect(Process %x  Address %x  flProtect %x)\n",
+    DPRINT("MmSetPageProtect(Process %p  Address %p  flProtect %x)\n",
            Process, Address, flProtect);
 
     Attributes = ProtectToPTE(flProtect);
@@ -990,7 +862,8 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
     }
     Pte = InterlockedExchangePte(Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY)));
 
-    if (!(Pte & PA_PRESENT))
+    // We should be able to bring a page back from PAGE_NOACCESS
+    if ((Pte & 0x800) || !(Pte >> PAGE_SHIFT))
     {
         DPRINT1("Invalid Pte %lx\n", Pte);
         KeBugCheck(MEMORY_MANAGEMENT);
@@ -1002,51 +875,12 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
         MmUnmapPageTable(Pt);
 }
 
-/*
- * @implemented
- */
-PHYSICAL_ADDRESS NTAPI
-MmGetPhysicalAddress(PVOID vaddr)
-/*
- * FUNCTION: Returns the physical address corresponding to a virtual address
- */
-{
-    PHYSICAL_ADDRESS p;
-    ULONG Pte;
-
-    DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr);
-    Pte = MmGetPageEntryForProcess(NULL, vaddr);
-    if (Pte != 0 && (Pte & PA_PRESENT))
-    {
-        p.QuadPart = PAGE_MASK(Pte);
-        p.u.LowPart |= (ULONG_PTR)vaddr & (PAGE_SIZE - 1);
-    }
-    else
-    {
-        p.QuadPart = 0;
-    }
-    return p;
-}
-
 VOID
 INIT_FUNCTION
 NTAPI
 MmInitGlobalKernelPageDirectory(VOID)
 {
-    ULONG i;
-    PULONG CurrentPageDirectory = (PULONG)PAGEDIRECTORY_MAP;
-
-    DPRINT("MmInitGlobalKernelPageDirectory()\n");
-
-    for (i = ADDR_TO_PDE_OFFSET(MmSystemRangeStart); i < 1024; i++)
-    {
-        if (i != ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) &&
-            i != ADDR_TO_PDE_OFFSET(HYPERSPACE) &&
-            0 == MmGlobalKernelPageDirectory[i] && 0 != CurrentPageDirectory[i])
-        {
-            MmGlobalKernelPageDirectory[i] = CurrentPageDirectory[i];
-        }
-    }
+    /* Nothing to do here */
 }
 
 /* EOF */