Commit in reactos/ntoskrnl/mm/i386 on MAIN
page.c+397-3581.71 -> 1.72
- Removed most of the calls to KeAttachProcess/KeDetachProcess.  
- Used the kernel map to map page tables from other process's. 
  In the future this should be replaced by a per process kernel map (hyperspace map).

reactos/ntoskrnl/mm/i386
page.c 1.71 -> 1.72
diff -u -r1.71 -r1.72
--- page.c	19 Aug 2004 21:47:51 -0000	1.71
+++ page.c	7 Sep 2004 11:08:16 -0000	1.72
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: page.c,v 1.71 2004/08/19 21:47:51 hbirr Exp $
+/* $Id: page.c,v 1.72 2004/09/07 11:08:16 hbirr Exp $
  *
  * PROJECT:     ReactOS kernel
  * FILE:        ntoskrnl/mm/i386/page.c
@@ -57,9 +57,10 @@
 
 ULONG MmGlobalKernelPageDirectory[1024] = {0, };
 
-#if defined(__GNUC__)
 #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)
@@ -119,18 +120,22 @@
    return(Attributes);
 }
 
-#define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (4 * 1024 * 1024))
+#define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (1024 * PAGE_SIZE))
 
 #define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \
                                 ((((ULONG)(v)) / (1024 * 1024))&(~0x3)))
 #define ADDR_TO_PTE(v) (PULONG)(PAGETABLE_MAP + ((((ULONG)(v) / 1024))&(~0x3)))
 
-#define ADDR_TO_PDE_OFFSET(v) ((((ULONG)(v)) / (4 * 1024 * 1024)))
+#define ADDR_TO_PDE_OFFSET(v) ((((ULONG)(v)) / (1024 * PAGE_SIZE)))
+
+#define ADDR_TO_PTE_OFFSET(v)  ((((ULONG)(v)) % (1024 * PAGE_SIZE)) / PAGE_SIZE) 
 
 NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process)
 {
    PUSHORT LdtDescriptor;
    ULONG LdtBase;
+   PULONG PageDir, Pde;
+   ULONG i, j;
 
    DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process);
 
@@ -145,6 +150,38 @@
    {
       ExFreePool((PVOID) LdtBase);
    }
+   PageDir = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT);
+   for (i = 0; i < ADDR_TO_PDE_OFFSET(KERNEL_BASE); i++)
+   {
+      if (PageDir[i] != 0)
+      {
+         DPRINT1("Pde for %08x - %08x is not freed, RefCount %d\n", 
+	         i * 4 * 1024 * 1024, (i + 1) * 4 * 1024 * 1024 - 1, 
+		 Process->AddressSpace.PageTableRefCountTable[i]);
+	 Pde = ExAllocatePageWithPhysPage(PageDir[i] >> PAGE_SHIFT);
+	 for (j = 0; j < 1024; j++)
+	 {
+	    if(Pde[j] != 0)
+	    {
+	       if (Pde[j] & PA_PRESENT)
+	       {
+	          DPRINT1("Page at %08x is not freed\n",
+		          i * 4 * 1024 * 1024 + j * PAGE_SIZE);
+	       }
+	       else
+	       {
+	          DPRINT1("Swapentry %x at %x is not freed\n",
+		          Pde[j], i * 4 * 1024 * 1024 + j * PAGE_SIZE);
+	       }
+
+	    }
+	 }
+	 ExUnmapPage(Pde);
+	 MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(PageDir[i]));
+      }
+   }
+   ExUnmapPage(PageDir);
+
 
    MmReleasePageMemoryConsumer(MC_NPPOOL, Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT);
 #if defined(__GNUC__)
@@ -229,7 +266,7 @@
       if (PageTable[i] != 0)
       {
          DbgPrint("Page table entry not clear at %x/%x (is %x)\n",
-                  ((ULONG)Address / 4*1024*1024), i, PageTable[i]);
+                  ((ULONG)Address / (4*1024*1024)), i, PageTable[i]);
          KEBUGCHECK(0);
       }
    }
@@ -252,102 +289,133 @@
    }
 }
 
-static PULONG MmGetPageEntry(PVOID PAddress, BOOL CreatePde)
-/*
- * FUNCTION: Get a pointer to the page table entry for a virtual address
- */
+static PULONG 
+MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
 {
-   PULONG Pde, kePde;
-   PFN_TYPE Pfn;
-   ULONG Attributes;
+   ULONG PdeOffset = ADDR_TO_PDE_OFFSET(Address);
    NTSTATUS Status;
-
-   DPRINT("MmGetPageEntry(Address %x)\n", PAddress);
-
-   Pde = ADDR_TO_PDE(PAGE_ROUND_DOWN(PAddress));
-   if (*Pde == 0)
+   PFN_TYPE Pfn;
+   ULONG Entry;
+   PULONG Pt, PageDir;
+   
+   if (Address < (PVOID)KERNEL_BASE && Process && Process != PsGetCurrentProcess())
+   {
+      PageDir = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT);
+      if (PageDir == NULL)
+      {
+         KEBUGCHECK(0);
+      }
+      if (PageDir[PdeOffset] == 0)
+      {
+         if (Create == FALSE)
+	 {
+	    ExUnmapPage(PageDir);
+	    return NULL;
+	 }
+         Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
+	 if (!NT_SUCCESS(Status) || Pfn == 0)
+	 {
+	    KEBUGCHECK(0);
+	 }
+         Entry = InterlockedCompareExchange(&PageDir[PdeOffset], PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
+	 if (Entry != 0)
+	 {
+	    MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
+	    Pfn = PTE_TO_PFN(Entry);
+	 }
+      }
+      else
+      {
+         Pfn = PTE_TO_PFN(PageDir[PdeOffset]);
+      }
+      ExUnmapPage(PageDir);
+      DPRINT("%d\n", Pfn);
+      Pt = ExAllocatePageWithPhysPage(Pfn);
+      if (Pt == NULL)
+      {
+         KEBUGCHECK(0);
+      }
+      return Pt + ADDR_TO_PTE_OFFSET(Address);
+   }
+   PageDir = ADDR_TO_PDE(Address);
+   if (*PageDir == 0)
    {
-      if (PAddress >= (PVOID)KERNEL_BASE)
+      if (Address >= (PVOID)KERNEL_BASE)
       {
-         kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress);
-         if (*kePde == 0)
+         if (MmGlobalKernelPageDirectory[PdeOffset] == 0)
 	 {
-            if (CreatePde == FALSE)
-            {
+	    if (Create == FALSE)
+	    {
                return NULL;
-            }
+	    }
             Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
-            if (!NT_SUCCESS(Status) || Pfn == 0)
-            {
-               KEBUGCHECK(0);
-            }
-	    Attributes =  PA_PRESENT | PA_READWRITE;
+	    if (!NT_SUCCESS(Status) || Pfn == 0)
+	    {
+	       KEBUGCHECK(0);
+	    }
+	    Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE;
             if (Ke386CpuidFlags & X86_FEATURE_PGE)
 	    {
-	       Attributes |= PA_GLOBAL;
+	       Entry |= PA_GLOBAL;
 	    }
-            if (0 == InterlockedCompareExchange(kePde, PFN_TO_PTE(Pfn) | Attributes, 0))
+	    if(0 != InterlockedCompareExchange(&MmGlobalKernelPageDirectory[PdeOffset], Entry, 0))
 	    {
-	       Pfn = 0;
+	       MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
 	    }
 	 }
-	 else
-	 {
-	    Pfn = 0;
-	 }
-	 *Pde = *kePde;
-#if 0
-	 /* Non existing mappings are not cached within the tlb. We must not invalidate this entry */
-         FLUSH_TLB_ONE(ADDR_TO_PTE(PAddress));
-#endif
+         *PageDir =MmGlobalKernelPageDirectory[PdeOffset];
       }
       else
       {
-         if (CreatePde == FALSE)
-         {
+	 if (Create == FALSE)
+	 {
             return NULL;
-         }
+	 }
          Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
-         if (!NT_SUCCESS(Status) || Pfn == 0)
-         {
-            KEBUGCHECK(0);
-         }
-         if (0 == InterlockedCompareExchange(Pde, PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0))
+	 if (!NT_SUCCESS(Status) || Pfn == 0)
 	 {
-	    Pfn = 0;
+	    KEBUGCHECK(0);
+	 }
+         Entry = InterlockedCompareExchange(PageDir, PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
+	 if (Entry != 0)
+	 {
+	    MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
 	 }
-#if 0
-	 /* Non existing mappings are not cached within the tlb. We must not invalidate this entry */
-         FLUSH_TLB_ONE(ADDR_TO_PTE(PAddress));
-#endif
-      }
-      if (Pfn != 0)
-      {
-	 MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
       }
    }
-   return (PULONG)ADDR_TO_PTE(PAddress);
+   return (PULONG)ADDR_TO_PTE(Address); 
 }
 
-static ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
+BOOLEAN MmUnmapPageTable(PULONG Pt)
 {
-   PULONG Pte;
-   ULONG oldPte;
-   PEPROCESS CurrentProcess = PsGetCurrentProcess();
-
-   if (Process != NULL && Process != CurrentProcess)
+   if (Pt >= (PULONG)PAGETABLE_MAP && Pt < (PULONG)PAGETABLE_MAP + 1024*1024)
    {
-      KeAttachProcess(Process);
+      return TRUE;
    }
-   Pte = MmGetPageEntry(Address, FALSE);
-   oldPte = Pte != NULL ? *Pte : 0;
-   if (Process != NULL && Process != CurrentProcess)
+   if (Pt)
    {
-      KeDetachProcess();
+      ExUnmapPage((PVOID)PAGE_ROUND_DOWN(Pt));
    }
-   return oldPte;
+   return FALSE;
+
 }
 
+static ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
+{
+   ULONG Pte;
+   PULONG Pt;
+
+   Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+   if (Pt)
+   {
+      Pte = *Pt;
+   
+      MmUnmapPageTable(Pt);
+      return Pte;
+   }
+   return 0;
+}
+	    
 PFN_TYPE
 MmGetPfnForProcess(PEPROCESS Process,
                    PVOID Address)
@@ -369,44 +437,33 @@
  * FUNCTION: Delete a virtual mapping 
  */
 {
-   PULONG Pte;
-   ULONG oldPte;
-   PEPROCESS CurrentProcess = PsGetCurrentProcess();
+   ULONG Pte;
+   PULONG Pt;
    BOOLEAN WasValid;
 
-   /*
-    * If we are setting a page in another process we need to be in its
-    * context.
-    */
-   if (Process != NULL && Process != CurrentProcess)
-   {
-      KeAttachProcess(Process);
-   }
-
-   Pte = MmGetPageEntry(Address, FALSE);
-   if (Pte == NULL)
+   Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+   if (Pt == NULL)
    {
       KEBUGCHECK(0);
    }
 
+
    /*
     * Atomically set the entry to zero and get the old value.
     */
-   oldPte = *Pte;
-   *Pte = oldPte & (~PA_PRESENT);
-   FLUSH_TLB_ONE(Address);
-   WasValid = (PAGE_MASK(oldPte) != 0);
-   if (!WasValid)
+   do
    {
-      KEBUGCHECK(0);
-   }
+     Pte = *Pt;
+   } while (Pte != InterlockedCompareExchange(Pt, Pte & ~PA_PRESENT, Pte)); 
 
-   /*
-    * If necessary go back to the original context
-    */
-   if (Process != NULL && Process != CurrentProcess)
+   if (MmUnmapPageTable(Pt) || Address >= (PVOID)KERNEL_BASE)
    {
-      KeDetachProcess();
+      FLUSH_TLB_ONE(Address);
+   }
+   WasValid = (PAGE_MASK(Pte) != 0);
+   if (!WasValid)
+   {
+      KEBUGCHECK(0);
    }
 
    /*
@@ -414,31 +471,26 @@
     */
    if (WasDirty != NULL)
    {
-      *WasDirty = oldPte & PA_DIRTY;
+      *WasDirty = Pte & PA_DIRTY;
    }
    if (Page != NULL)
    {
-      *Page = PTE_TO_PFN(oldPte);
+      *Page = PTE_TO_PFN(Pte);
    }
 }
 
 VOID
 MmRawDeleteVirtualMapping(PVOID Address)
 {
-   PULONG Pte;
+   PULONG Pt;
 
-   /*
-    * Set the page directory entry, we may have to copy the entry from
-    * the global page directory.
-    */
-
-   Pte = MmGetPageEntry(Address, FALSE);
-   if (Pte)
+   Pt = MmGetPageTableForProcess(NULL, Address, FALSE);
+   if (Pt && *Pt)
    {
       /*
        * Set the entry to zero
        */
-      *Pte = 0;
+      *Pt = 0;
       FLUSH_TLB_ONE(Address);
    }
 }
@@ -450,27 +502,17 @@
  * FUNCTION: Delete a virtual mapping 
  */
 {
-   ULONG oldPte;
-   PULONG Pte;
-   PEPROCESS CurrentProcess = PsGetCurrentProcess();
+   ULONG Pte;
+   PULONG Pt;
    BOOLEAN WasValid;
 
-   /*
-    * If we are setting a page in another process we need to be in its
-    * context.
-    */
-   if (Process != NULL && Process != CurrentProcess)
-   {
-      KeAttachProcess(Process);
-   }
+   DPRINT("MmDeleteVirtualMapping(%x, %x, %d, %x, %x)\n",
+           Process, Address, FreePage, WasDirty, Page);
+
+   Pt = MmGetPageTableForProcess(Process, Address, FALSE);
 
-   Pte = MmGetPageEntry(Address, FALSE);
-   if (Pte == NULL)
+   if (Pt == NULL)
    {
-      if (Process != NULL && Process != CurrentProcess)
-      {
-         KeDetachProcess();
-      }
       if (WasDirty != NULL)
       {
          *WasDirty = FALSE;
@@ -485,19 +527,22 @@
    /*
     * Atomically set the entry to zero and get the old value.
     */
-   oldPte = InterlockedExchange(Pte, 0);
-   if (oldPte)
+   Pte = InterlockedExchange(Pt, 0);
+
+   if ((MmUnmapPageTable(Pt) || Address >=(PVOID)KERNEL_BASE) && Pte)
    {
-      FLUSH_TLB_ONE(Address);
+     FLUSH_TLB_ONE(Address);
    }
-   WasValid = (PAGE_MASK(oldPte) != 0);
+
+   WasValid = (PAGE_MASK(Pte) != 0);
    if (WasValid)
    {
-      MmMarkPageUnmapped(PTE_TO_PFN(oldPte));
+      MmMarkPageUnmapped(PTE_TO_PFN(Pte));
    }
+
    if (FreePage && WasValid)
    {
-      MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(oldPte));
+      MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(Pte));
    }
 
    /*
@@ -519,23 +564,15 @@
    }
 
    /*
-    * If necessary go back to the original context
-    */
-   if (Process != NULL && Process != CurrentProcess)
-   {
-      KeDetachProcess();
-   }
-
-   /*
     * Return some information to the caller
     */
    if (WasDirty != NULL)
    {
-      *WasDirty = oldPte & PA_DIRTY ? TRUE : FALSE;
+      *WasDirty = Pte & PA_DIRTY ? TRUE : FALSE;
    }
    if (Page != NULL)
    {
-      *Page = PTE_TO_PFN(oldPte);
+      *Page = PTE_TO_PFN(Pte);
    }
 }
 
@@ -546,28 +583,13 @@
  * FUNCTION: Delete a virtual mapping 
  */
 {
-   ULONG oldPte;
-   PULONG Pte;
-   PEPROCESS CurrentProcess = PsGetCurrentProcess();
-   BOOLEAN WasValid = FALSE;
-
-   /*
-    * If we are setting a page in another process we need to be in its
-    * context.
-    */
-   if (Process != NULL && Process != CurrentProcess)
-   {
-      KeAttachProcess(Process);
-   }
+   ULONG Pte;
+   PULONG Pt;
 
-   Pte = MmGetPageEntry(Address, FALSE);
+   Pt = MmGetPageTableForProcess(Process, Address, FALSE);
  
-   if (Pte == NULL)
+   if (Pt == NULL)
    {
-      if (Process != NULL && Process != CurrentProcess)
-      {
-         KeDetachProcess();
-      }
       *SwapEntry = 0;
       return;
    }
@@ -575,17 +597,19 @@
    /*
     * Atomically set the entry to zero and get the old value.
     */
-   oldPte = InterlockedExchange(Pte, 0);
-   FLUSH_TLB_ONE(Address);
+   Pte = InterlockedExchange(Pt, 0);
 
-   WasValid = PAGE_MASK(oldPte) == 0 ? FALSE : TRUE;
+   if (MmUnmapPageTable(Pt) || Address >= (PVOID)KERNEL_BASE)
+   {
+      FLUSH_TLB_ONE(Address);
+   }
 
    /*
     * Decrement the reference count for this page table.
     */
-   if (Process != NULL && WasValid &&
-         Process->AddressSpace.PageTableRefCountTable != NULL &&
-         Address < (PVOID)KERNEL_BASE)
+   if (Process != NULL && Pte &&
+       Process->AddressSpace.PageTableRefCountTable != NULL &&
+       Address < (PVOID)KERNEL_BASE)
    {
       PUSHORT Ptrc;
 
@@ -598,34 +622,28 @@
       }
    }
 
-   /*
-    * If necessary go back to the original context
-    */
-   if (Process != NULL && Process != CurrentProcess)
-   {
-      KeDetachProcess();
-   }
 
    /*
     * Return some information to the caller
     */
-   *SwapEntry = oldPte >> 1;
+   *SwapEntry = Pte >> 1;
 }
 
 BOOLEAN
 Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
 {
-   PULONG Pte, Pde;
+   PULONG Pt, Pde;
+
 
    Pde = ADDR_TO_PDE(PAddress);
    if (*Pde == 0)
    {
-      Pte = MmGetPageEntry(PAddress, FALSE);
+      Pt = MmGetPageTableForProcess(NULL, PAddress, FALSE);
 #if 0
       /* Non existing mappings are not cached within the tlb. We must not invalidate this entry */
       FLASH_TLB_ONE(PAddress);
 #endif
-      if (Pte != NULL)
+      if (Pt != NULL)
       {
          return TRUE;
       }
@@ -641,145 +659,136 @@
 BOOLEAN
 MmIsAccessedAndResetAccessPage(PEPROCESS Process, PVOID Address)
 {
-   ULONG oldPte;
-   PULONG Pte;
-   PEPROCESS CurrentProcess;
+   PULONG Pt;
+   ULONG Pte;
 
-   if (Process)
+   if (Address < (PVOID)KERNEL_BASE && Process == NULL)
    {
-      CurrentProcess = PsGetCurrentProcess();
-      if (Process != CurrentProcess)
-      {
-         KeAttachProcess(Process);
-      }
-   }
-   else
-   {
-      if (((ULONG)Address & ~0xFFF) < KERNEL_BASE)
-      {
-         DPRINT1("MmIsAccessedAndResetAccessPage is called for user space without a process.\n");
-         KEBUGCHECK(0);
-      }
-      CurrentProcess = NULL;
+     DPRINT1("MmIsAccessedAndResetAccessPage is called for user space without a process.\n");
+     KEBUGCHECK(0);
    }
 
-   Pte = MmGetPageEntry(Address, FALSE);
-   if (Pte == NULL)
+   Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+   if (Pt == NULL)
    {
       KEBUGCHECK(0);
    }
-   oldPte = *Pte;
-   if (oldPte & PA_ACCESSED)
+   
+   do
    {
-      *Pte = *Pte & (~PA_ACCESSED);
-      FLUSH_TLB_ONE(Address);
+      Pte = *Pt;
+   } while (Pte != InterlockedCompareExchange(Pt, Pte & ~PA_ACCESSED, Pte));
+
+   if (Pte & PA_ACCESSED)
+   {
+      if (MmUnmapPageTable(Pt) || Address >= (PVOID)KERNEL_BASE)
+      {
+         FLUSH_TLB_ONE(Address);
+      }
+      return TRUE;
    }
-   if (Process != CurrentProcess)
+   else
    {
-      KeDetachProcess();
+      MmUnmapPageTable(Pt);
+      return FALSE;
    }
-
-   return oldPte & PA_ACCESSED ? TRUE : FALSE;
 }
 
 VOID MmSetCleanPage(PEPROCESS Process, PVOID Address)
 {
-   PULONG Pte;
-   PEPROCESS CurrentProcess;
+   PULONG Pt;
+   ULONG Pte;
 
-   if (Process)
+   if (Address < (PVOID)KERNEL_BASE && Process == NULL)
    {
-      CurrentProcess = PsGetCurrentProcess();
-      if (Process != CurrentProcess)
-      {
-         KeAttachProcess(Process);
-      }
-   }
-   else
-   {
-      if (Address < (PVOID)KERNEL_BASE)
-      {
-         DPRINT1("MmSetCleanPage is called for user space without a process.\n");
-         KEBUGCHECK(0);
-      }
-      CurrentProcess = NULL;
+      DPRINT1("MmSetCleanPage is called for user space without a process.\n");
+      KEBUGCHECK(0);
    }
-   Pte = MmGetPageEntry(Address, FALSE);
-   if (Pte == NULL)
+
+   Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+
+   if (Pt == NULL)
    {
       KEBUGCHECK(0);
    }
-   if (*Pte & PA_DIRTY)
+
+   do
    {
-      *Pte = *Pte & (~PA_DIRTY);
-      FLUSH_TLB_ONE(Address);
+      Pte = *Pt;
+   } while (Pte != InterlockedCompareExchange(Pt, Pte & ~PA_DIRTY, Pte));
+
+   if (Pte & PA_DIRTY)
+   {
+      if (MmUnmapPageTable(Pt) || Address > (PVOID)KERNEL_BASE)
+      {
+         FLUSH_TLB_ONE(Address);
+      }
    }
-   if (Process != CurrentProcess)
+   else
    {
-      KeDetachProcess();
+      MmUnmapPageTable(Pt);
    }
 }
 
 VOID MmSetDirtyPage(PEPROCESS Process, PVOID Address)
 {
-   PULONG Pte;
-   PEPROCESS CurrentProcess = NULL;
+   PULONG Pt;
+   ULONG Pte;
 
-   if (Process)
-   {
-      CurrentProcess = PsGetCurrentProcess();
-      if (Process != CurrentProcess)
-      {
-         KeAttachProcess(Process);
-      }
-   }
-   else
+   if (Address < (PVOID)KERNEL_BASE && Process == NULL)
    {
-      if (Address < (PVOID)KERNEL_BASE)
-      {
-         DPRINT1("MmSetDirtyPage is called for user space without a process.\n");
-         KEBUGCHECK(0);
-      }
-      CurrentProcess = NULL;
+      DPRINT1("MmSetDirtyPage is called for user space without a process.\n");
+      KEBUGCHECK(0);
    }
-   Pte = MmGetPageEntry(Address, FALSE);
-   if (Pte == NULL)
+
+   Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+   if (Pt == NULL)
    {
       KEBUGCHECK(0);
    }
-   if (!(*Pte & PA_DIRTY))
+
+   do
    {
-      *Pte = *Pte | PA_DIRTY;
-      FLUSH_TLB_ONE(Address);
+      Pte = *Pt;
+   } while (Pte != InterlockedCompareExchange(Pt, Pte | PA_DIRTY, Pte));
+   if (!(Pte & PA_DIRTY))
+   {
+      if (MmUnmapPageTable(Pt) || Address > (PVOID)KERNEL_BASE)
+      {
+         FLUSH_TLB_ONE(Address);
+      }
    }
-   if (Process != CurrentProcess)
+   else
    {
-      KeDetachProcess();
+      MmUnmapPageTable(Pt);
    }
 }
 
 VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
 {
-   PULONG Pte;
-   PEPROCESS CurrentProcess = PsGetCurrentProcess();
+   PULONG Pt;
+   ULONG Pte;
 
-   if (Process != CurrentProcess)
-   {
-      KeAttachProcess(Process);
-   }
-   Pte = MmGetPageEntry(Address, FALSE);
-   if (Pte == NULL)
+   Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+   if (Pt == NULL)
    {
       KEBUGCHECK(0);
    }
-   if (!(*Pte & PA_PRESENT))
+
+   do
    {
-      *Pte = *Pte | PA_PRESENT;
-      FLUSH_TLB_ONE(Address);
+      Pte = *Pt;
+   } while (Pte != InterlockedCompareExchange(Pt, Pte | PA_PRESENT, Pte));
+   if (!(Pte & PA_PRESENT))
+   {
+      if (MmUnmapPageTable(Pt) || Address > (PVOID)KERNEL_BASE)
+      {
+         FLUSH_TLB_ONE(Address);
+      }
    }
-   if (Process != CurrentProcess)
+   else
    {
-      KeDetachProcess();
+      MmUnmapPageTable(Pt);
    }
 }
 
@@ -801,10 +810,14 @@
                                 PPFN_TYPE Pages,
 				ULONG PageCount)
 {
-   ULONG Attributes, oldPte;
-   PULONG Pte;
+   ULONG Attributes, Pte;
+   PULONG Pt;
    ULONG i;
    PVOID Addr;
+   ULONG PdeOffset, oldPdeOffset;
+
+   DPRINT("MmCreateVirtualMappingForKernel(%x, %x, %x, %d)\n",
+           Address, flProtect, Pages, PageCount);
 
    if (Address < (PVOID)KERNEL_BASE)
    {
@@ -817,7 +830,16 @@
    {
       Attributes |= PA_GLOBAL;
    }
+
    Addr = Address;
+   oldPdeOffset = ADDR_TO_PDE_OFFSET(Addr);
+   Pt = MmGetPageTableForProcess(NULL, Addr, TRUE);
+   if (Pt == NULL)
+   {
+      KEBUGCHECK(0);
+   }
+   Pt--;
+
    for (i = 0; i < PageCount; i++, Addr += PAGE_SIZE)
    {
       if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
@@ -828,21 +850,28 @@
          KEBUGCHECK(0);
       }
 
-      Pte = MmGetPageEntry(Addr, TRUE);
-      if (Pte == NULL)
+      PdeOffset = ADDR_TO_PDE_OFFSET(Addr);
+      if (oldPdeOffset != PdeOffset)
       {
-         KEBUGCHECK(0);
+         Pt = MmGetPageTableForProcess(NULL, Addr, TRUE);
+	 if (Pt == NULL)
+	 {
+	    KEBUGCHECK(0);
+	 }
       }
-      oldPte = *Pte;
-      if (PAGE_MASK((oldPte)) != 0)
+      else
       {
-         KEBUGCHECK(0);
+         Pt++;
       }
-      *Pte = PFN_TO_PTE(Pages[i]) | Attributes;
-      if (oldPte != 0)
+      oldPdeOffset = PdeOffset;
+
+      Pte = *Pt;
+      if (Pte != 0)
       {
-         FLUSH_TLB_ONE(Addr);
+         DPRINT1("%x %x %x\n", Address, Pt, Pte << PAGE_SHIFT);
+         KEBUGCHECK(0);
       }
+      *Pt = PFN_TO_PTE(Pages[i]) | Attributes;
    }
 
    return(STATUS_SUCCESS);
@@ -853,18 +882,9 @@
                         PVOID Address,
                         SWAPENTRY SwapEntry)
 {
-   PEPROCESS CurrentProcess;
-   PULONG Pte;
-   ULONG oldPte;
+   PULONG Pt;
+   ULONG Pte;
 
-   if (Process != NULL)
-   {
-      CurrentProcess = PsGetCurrentProcess();
-   }
-   else
-   {
-      CurrentProcess = NULL;
-   }
 
    if (Process == NULL && Address < (PVOID)KERNEL_BASE)
    {
@@ -881,24 +901,32 @@
       KEBUGCHECK(0);
    }
 
-   if (Process != NULL && Process != CurrentProcess)
+   Pt = MmGetPageTableForProcess(Process, Address, TRUE);
+   if (Pt == NULL)
    {
-      KeAttachProcess(Process);
+      KEBUGCHECK(0);
    }
-   Pte = MmGetPageEntry(Address, TRUE);
-   if (Pte == NULL)
+   Pte = *Pt;
+   if (PAGE_MASK((Pte)) != 0)
    {
-      KEBUGCHECK(0);
+      MmMarkPageUnmapped(PTE_TO_PFN((Pte)));
    }
-   oldPte = *Pte;
-   if (PAGE_MASK((oldPte)) != 0)
+   *Pt = SwapEntry << 1;
+   if (Pte != 0) 
    {
-      MmMarkPageUnmapped(PTE_TO_PFN((oldPte)));
+      if (MmUnmapPageTable(Pt) || Address > (PVOID)KERNEL_BASE)
+      {
+         FLUSH_TLB_ONE(Address);
+      }
    }
-   *Pte = SwapEntry << 1;
+   else
+   {
+      MmUnmapPageTable(Pt);
+   }
+
    if (Process != NULL &&
-         Process->AddressSpace.PageTableRefCountTable != NULL &&
-         Address < (PVOID)KERNEL_BASE)
+       Process->AddressSpace.PageTableRefCountTable != NULL &&
+       Address < (PVOID)KERNEL_BASE)
    {
       PUSHORT Ptrc;
 
@@ -906,14 +934,6 @@
 
       Ptrc[ADDR_TO_PAGE_TABLE(Address)]++;
    }
-   if (oldPte != 0)
-   {
-      FLUSH_TLB_ONE(Address);
-   }
-   if (Process != NULL && Process != CurrentProcess)
-   {
-      KeDetachProcess();
-   }
    return(STATUS_SUCCESS);
 }
 
@@ -925,31 +945,43 @@
                              PPFN_TYPE Pages,
                              ULONG PageCount)
 {
-   PEPROCESS CurrentProcess;
    ULONG Attributes;
-   PVOID Addr = Address;
+   PVOID Addr;
    ULONG i;
-   PULONG Pte;
-   ULONG oldPte;
+   PULONG Pt = NULL;
+   ULONG Pte;
+   ULONG oldPdeOffset, PdeOffset;
 
-   if (Process != NULL)
+   DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x, %d)\n",
+            Process, Address, flProtect, Pages, PageCount);
+   
+   if (Process == NULL)
    {
-      CurrentProcess = PsGetCurrentProcess();
+      if (Address < (PVOID)KERNEL_BASE)
+      {
+         DPRINT1("No process\n");
+         KEBUGCHECK(0);
+      }
+      if (PageCount > 0x10000 || 
+	  (ULONG_PTR) Address / PAGE_SIZE + PageCount > 0x100000)
+      {
+         DPRINT1("Page count to large\n");
+	 KEBUGCHECK(0);
+      }
    }
    else
    {
-      CurrentProcess = NULL;
-   }
-
[truncated at 1000 lines; 161 more skipped]
CVSspam 0.2.8