update for HEAD-2003091401
[reactos.git] / ntoskrnl / mm / i386 / page.c
index 185921c..d8f0ece 100644 (file)
@@ -95,7 +95,7 @@ ProtectToPTE(ULONG flProtect)
   else
     {
       DPRINT1("Unknown main protection type.\n");
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   if (!(flProtect & PAGE_SYSTEM))
     {
@@ -115,14 +115,29 @@ ProtectToPTE(ULONG flProtect)
 #define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (4 * 1024 * 1024))
 
 #define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \
-                                (((ULONG)v / (1024 * 1024))&(~0x3)))
+                                ((((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)) / (4 * 1024 * 1024)))
 
 NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process)
 {
+   PUSHORT LdtDescriptor;
+   ULONG LdtBase;
+
    DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process);
+
+   LdtDescriptor = (PUSHORT) &Process->Pcb.LdtDescriptor[0];
+   LdtBase = LdtDescriptor[1] |
+                   ((LdtDescriptor[2] & 0xff) << 16) |
+                   ((LdtDescriptor[3] & ~0xff) << 16);
+
+   DPRINT("LdtBase: %x\n", LdtBase);
+   
+   if (LdtBase)
+     {
+       ExFreePool((PVOID) LdtBase);
+     }
    
    MmReleasePageMemoryConsumer(MC_NPPOOL, Process->Pcb.DirectoryTableBase);
    Process->Pcb.DirectoryTableBase.QuadPart = 0LL;
@@ -135,9 +150,7 @@ NTSTATUS MmCopyMmInfo(PEPROCESS Src, PEPROCESS Dest)
 {
    PHYSICAL_ADDRESS PhysPageDirectory;
    PULONG PageDirectory;
-   PULONG CurrentPageDirectory;
    PKPROCESS KProcess = &Dest->Pcb;
-   ULONG i;
    
    DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src, Dest);
    
@@ -148,17 +161,12 @@ NTSTATUS MmCopyMmInfo(PEPROCESS Src, PEPROCESS Dest)
      }
    PhysPageDirectory = MmGetPhysicalAddress(PageDirectory);
    KProcess->DirectoryTableBase = PhysPageDirectory;   
-   CurrentPageDirectory = (PULONG)PAGEDIRECTORY_MAP;
    
-   memset(PageDirectory,0,PAGE_SIZE);
-   for (i=768; i<896; i++)
-     {
-       PageDirectory[i] = CurrentPageDirectory[i];
-     }
-   for (i=961; i<1024; i++)
-     {
-       PageDirectory[i] = CurrentPageDirectory[i];
-     }
+   memset(PageDirectory,0, ADDR_TO_PDE_OFFSET(KERNEL_BASE) * sizeof(ULONG));
+   memcpy(PageDirectory + ADDR_TO_PDE_OFFSET(KERNEL_BASE), 
+          MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(KERNEL_BASE), 
+         (1024 - ADDR_TO_PDE_OFFSET(KERNEL_BASE)) * sizeof(ULONG));
+
    DPRINT("Addr %x\n",PAGETABLE_MAP / (4*1024*1024));
    PageDirectory[PAGETABLE_MAP / (4*1024*1024)] = 
      PhysPageDirectory.u.LowPart | PA_PRESENT | PA_READWRITE;
@@ -180,7 +188,7 @@ VOID MmDeletePageTable(PEPROCESS Process, PVOID Address)
    *(ADDR_TO_PDE(Address)) = 0;
    if (Address >= (PVOID)KERNEL_BASE)
      {
-         KeBugCheck(0);
+         KEBUGCHECK(0);
 //       MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = 0;
      }
    FLUSH_TLB;
@@ -209,7 +217,7 @@ VOID MmFreePageTable(PEPROCESS Process, PVOID Address)
       {
          DbgPrint("Page table entry not clear at %x/%x (is %x)\n",
                  ((ULONG)Address / 4*1024*1024), i, PageTable[i]);
-        KeBugCheck(0);
+        KEBUGCHECK(0);
       }
    }
    npage = *(ADDR_TO_PDE(Address));
@@ -219,7 +227,7 @@ VOID MmFreePageTable(PEPROCESS Process, PVOID Address)
    if (Address >= (PVOID)KERNEL_BASE)
    {
 //    MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = 0;
-      KeBugCheck(0);
+      KEBUGCHECK(0);
    }
    else
    {
@@ -262,7 +270,7 @@ NTSTATUS MmGetPageEntry2(PVOID PAddress, PULONG* Pte, BOOLEAN MayWait)
            Status = MmRequestPageMemoryConsumer(MC_NPPOOL, MayWait, &npage);
            if (!NT_SUCCESS(Status))
            {
-              KeBugCheck(0);
+              KEBUGCHECK(0);
            }
            oldIrql = KeRaiseIrqlToSynchLevel();
            /* An other thread can set this pde entry, we must check again */
@@ -412,7 +420,7 @@ MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, PHYSIC
      }
    if ((*Pde) == 0)
      {
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
 
    /*
@@ -424,7 +432,7 @@ MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, PHYSIC
    WasValid = (PAGE_MASK(Pte) != 0);
    if (!WasValid)
      {
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
 
    /*
@@ -450,6 +458,38 @@ MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, PHYSIC
 }
 
 VOID
+MmRawDeleteVirtualMapping(PVOID Address)
+{
+   PULONG Pde, kePde;
+
+   /*
+    * Set the page directory entry, we may have to copy the entry from
+    * the global page directory.
+    */
+   Pde = ADDR_TO_PDE(Address);
+   if (*Pde == 0 && Address >= (PVOID)KERNEL_BASE)
+   {
+      kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(Address);
+      if (*kePde != 0)
+      {
+         *Pde = *kePde;
+        FLUSH_TLB;
+      }
+   }
+   
+   if (*Pde == 0)
+     {
+       return;
+     }
+
+   /*
+    * Set the entry to zero
+    */
+   *ADDR_TO_PTE(Address) = 0;
+   FLUSH_TLB;
+}
+
+VOID
 MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage,
                       BOOL* WasDirty, PHYSICAL_ADDRESS* PhysicalAddr)
 /*
@@ -758,7 +798,7 @@ PULONG MmGetPageEntry(PVOID PAddress)
            Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &npage);
             if (!NT_SUCCESS(Status))
            {
-              KeBugCheck(0);
+              KEBUGCHECK(0);
            }
            MiZeroPage(npage);
            oldIrql = KeRaiseIrqlToSynchLevel();
@@ -781,7 +821,7 @@ PULONG MmGetPageEntry(PVOID PAddress)
         Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &npage);
          if (!NT_SUCCESS(Status))
         {
-           KeBugCheck(0);
+           KEBUGCHECK(0);
         }
         MiZeroPage(npage);
         *Pde = npage.u.LowPart | PA_PRESENT | PA_READWRITE | PA_USER;
@@ -805,13 +845,27 @@ BOOLEAN
 MmIsAccessedAndResetAccessPage(PEPROCESS Process, PVOID Address)
 {
    PULONG PageEntry;
-   PEPROCESS CurrentProcess = PsGetCurrentProcess();
+   PEPROCESS CurrentProcess;
    BOOLEAN Accessed;
 
-   if (Process != CurrentProcess)
+   if (Process)
      {
-       KeAttachProcess(Process);
+       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;
+     }
+
    PageEntry = MmGetPageEntry(Address);
    Accessed = (*PageEntry) & PA_ACCESSED;
    if (Accessed)
@@ -830,11 +884,24 @@ MmIsAccessedAndResetAccessPage(PEPROCESS Process, PVOID Address)
 VOID MmSetCleanPage(PEPROCESS Process, PVOID Address)
 {
    PULONG PageEntry;
-   PEPROCESS CurrentProcess = PsGetCurrentProcess();
-   
-   if (Process != CurrentProcess)
+   PEPROCESS CurrentProcess;
+
+   if (Process)
      {
-       KeAttachProcess(Process);
+       CurrentProcess = PsGetCurrentProcess();
+       if (Process != CurrentProcess)
+         {
+          KeAttachProcess(Process);
+         }
+     }
+   else 
+     {
+       if (((ULONG)Address & ~0xFFF) < KERNEL_BASE)
+         {
+           DPRINT1("MmSetCleanPage is called for user space without a process.\n");
+           KEBUGCHECK(0);
+        }
+       CurrentProcess = NULL;
      }
    PageEntry = MmGetPageEntry(Address);
    (*PageEntry) = (*PageEntry) & (~PA_DIRTY);
@@ -848,11 +915,24 @@ VOID MmSetCleanPage(PEPROCESS Process, PVOID Address)
 VOID MmSetDirtyPage(PEPROCESS Process, PVOID Address)
 {
    PULONG PageEntry;
-   PEPROCESS CurrentProcess = PsGetCurrentProcess();
-   
-   if (Process != CurrentProcess)
+   PEPROCESS CurrentProcess = NULL;
+
+   if (Process)
      {
-       KeAttachProcess(Process);
+       CurrentProcess = PsGetCurrentProcess();
+       if (Process != CurrentProcess)
+         {
+          KeAttachProcess(Process);
+         }
+     }
+   else 
+     {
+       if (((ULONG)Address & ~0xFFF) < KERNEL_BASE)
+         {
+           DPRINT1("MmSetDirtyPage is called for user space without a process.\n");
+           KEBUGCHECK(0);
+        }
+       CurrentProcess = NULL;
      }
    PageEntry = MmGetPageEntry(Address);
    (*PageEntry) = (*PageEntry) | PA_DIRTY;
@@ -894,6 +974,45 @@ BOOLEAN MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
 }
 
 NTSTATUS 
+MmCreateVirtualMappingDump(PVOID Address, 
+                          ULONG flProtect,
+                          PHYSICAL_ADDRESS PhysicalAddress)
+{
+   ULONG Attributes;
+   PULONG Pte;
+   NTSTATUS Status;
+
+   if (Address < (PVOID)KERNEL_BASE)
+     {
+       DPRINT1("No process\n");
+       KEBUGCHECK(0);
+     }
+   
+   Attributes = ProtectToPTE(flProtect);
+   if (!(Attributes & PA_PRESENT) && PhysicalAddress.QuadPart != 0)
+     {
+       DPRINT1("Setting physical address but not allowing access at address "
+              "0x%.8X with attributes %x/%x.\n", 
+              Address, Attributes, flProtect);
+       KEBUGCHECK(0);
+     }
+   
+   Status = MmGetPageEntry2(Address, &Pte, FALSE);
+   if (!NT_SUCCESS(Status))
+     {
+       return(Status);
+     }
+   if (PAGE_MASK((*Pte)) != 0 && !((*Pte) & PA_PRESENT))
+     {
+       KEBUGCHECK(0);
+     }
+   *Pte = PhysicalAddress.QuadPart | Attributes;
+   FLUSH_TLB;
+   return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS 
 MmCreateVirtualMappingForKernel(PVOID Address, 
                                ULONG flProtect,
                                PHYSICAL_ADDRESS PhysicalAddress)
@@ -916,12 +1035,12 @@ MmCreateVirtualMappingForKernel(PVOID Address,
    if (Process == NULL && Address < (PVOID)KERNEL_BASE)
      {
        DPRINT1("No process\n");
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
    if (Process != NULL && Address >= (PVOID)KERNEL_BASE)
      {
        DPRINT1("Setting kernel address with process context\n");
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
    Attributes = ProtectToPTE(flProtect);
    
@@ -941,7 +1060,7 @@ MmCreateVirtualMappingForKernel(PVOID Address,
      }
    if (PAGE_MASK((*Pte)) != 0 && !((*Pte) & PA_PRESENT))
      {
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
    if (PAGE_MASK((*Pte)) != 0)
      {
@@ -950,7 +1069,7 @@ MmCreateVirtualMappingForKernel(PVOID Address,
    *Pte = PhysicalAddress.QuadPart | Attributes;
    if (Process != NULL && 
        Process->AddressSpace.PageTableRefCountTable != NULL &&
-       ADDR_TO_PAGE_TABLE(Address) < 768 &&
+       Address < (PVOID)KERNEL_BASE &&
        Attributes & PA_PRESENT)
      {
        PUSHORT Ptrc;
@@ -988,16 +1107,16 @@ MmCreatePageFileMapping(PEPROCESS Process,
   if (Process == NULL && Address < (PVOID)KERNEL_BASE)
     {
       DPRINT1("No process\n");
-      KeBugCheck(0);
+      KEBUGCHECK(0);
      }
   if (Process != NULL && Address >= (PVOID)KERNEL_BASE)
     {
       DPRINT1("Setting kernel address with process context\n");
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   if (SwapEntry & (1 << 31))
     {
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
 
   if (Process != NULL && Process != CurrentProcess)
@@ -1021,7 +1140,7 @@ MmCreatePageFileMapping(PEPROCESS Process,
   *Pte = SwapEntry << 1;
   if (Process != NULL && 
       Process->AddressSpace.PageTableRefCountTable != NULL &&
-      ADDR_TO_PAGE_TABLE(Address) < 768)
+      Address < (PVOID)KERNEL_BASE)
     {
       PUSHORT Ptrc;
       
@@ -1037,6 +1156,8 @@ MmCreatePageFileMapping(PEPROCESS Process,
   return(STATUS_SUCCESS);
 }
 
+
+
 NTSTATUS 
 MmCreateVirtualMappingUnsafe(PEPROCESS Process,
                             PVOID Address, 
@@ -1061,12 +1182,12 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
    if (Process == NULL && Address < (PVOID)KERNEL_BASE)
      {
        DPRINT1("No process\n");
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
    if (Process != NULL && Address >= (PVOID)KERNEL_BASE)
      {
        DPRINT1("Setting kernel address with process context\n");
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
    MmMarkPageMapped(PhysicalAddress);
    
@@ -1076,7 +1197,7 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
        DPRINT1("Setting physical address but not allowing access at address "
               "0x%.8X with attributes %x/%x.\n", 
               Address, Attributes, flProtect);
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
    
    if (Process != NULL && Process != CurrentProcess)
@@ -1095,7 +1216,7 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
      }
    if (PAGE_MASK((*Pte)) != 0 && !((*Pte) & PA_PRESENT))
      {
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
    if (PAGE_MASK((*Pte)) != 0)
      {
@@ -1104,7 +1225,7 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
    *Pte = PhysicalAddress.QuadPart | Attributes;
    if (Process != NULL && 
        Process->AddressSpace.PageTableRefCountTable != NULL &&
-       ADDR_TO_PAGE_TABLE(Address) < 768 &&
+       Address < (PVOID)KERNEL_BASE &&
        Attributes & PA_PRESENT)
      {
        PUSHORT Ptrc;
@@ -1131,7 +1252,7 @@ MmCreateVirtualMapping(PEPROCESS Process,
   if (!MmIsUsablePage(PhysicalAddress))
     {
       DPRINT1("Page at address %x not usable\n", PhysicalAddress);
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   
   return(MmCreateVirtualMappingUnsafe(Process,
@@ -1188,6 +1309,9 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
      }
 }
 
+/*
+ * @implemented
+ */
 PHYSICAL_ADDRESS STDCALL 
 MmGetPhysicalAddress(PVOID vaddr)
 /*
@@ -1213,4 +1337,36 @@ MmGetPhysicalAddress(PVOID vaddr)
 }
 
 
+VOID
+MmUpdateStackPageDir(PULONG LocalPageDir, PKTHREAD PThread)
+{
+  unsigned EntryBase = ADDR_TO_PDE_OFFSET(PThread->StackLimit);
+  unsigned EntryTop = ADDR_TO_PDE_OFFSET(PThread->InitialStack - PAGE_SIZE);
+
+  if (0 == LocalPageDir[EntryBase])
+    {
+      LocalPageDir[EntryBase] = MmGlobalKernelPageDirectory[EntryBase];
+    }
+  if (EntryBase != EntryTop && 0 == LocalPageDir[EntryTop])
+    {
+      LocalPageDir[EntryTop] = MmGlobalKernelPageDirectory[EntryTop];
+    }
+}
+
+VOID 
+MmInitGlobalKernelPageDirectory(VOID)
+{
+  ULONG i;
+  PULONG CurrentPageDirectory = (PULONG)PAGEDIRECTORY_MAP;
+
+  for (i = ADDR_TO_PDE_OFFSET(KERNEL_BASE); i < 1024; i++)
+    {
+      if (i != ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) && 
+         0 == MmGlobalKernelPageDirectory[i] && 0 != CurrentPageDirectory[i])
+        {
+          MmGlobalKernelPageDirectory[i] = CurrentPageDirectory[i];
+        }
+    }
+}
+
 /* EOF */