Testers: Please test this build.
authorSir Richard <sir_richard@svn.reactos.org>
Fri, 4 Jun 2010 17:49:36 +0000 (17:49 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Fri, 4 Jun 2010 17:49:36 +0000 (17:49 +0000)
[NTOS]: Implement a MI_MAKE_HARDWARE_PTE macro for the generation of valid kernel PTEs instead of always taking the ValidKernelPte and changing its flags. This macro will take into account the protection mask (up until now ignored) and use the array previously implemented to determine the correct hardware PTE settings. Assertions are also added to validate correct usage of the macro, and later revisions will fill out NT-specific fields to help deal with transition PTEs, page faults, etc.
[NTOS]: Make the stack code the first user of this macro, for the stack PTEs. Good testing base as we create kernel stacks very often.
[NTOS]: The NT MM ABI specifies that in between the allocation of a new PTE and its initialization as a valid PFN, the PTE entry should be an invalid PTE, and should only be marked valid after the PFN has been initialized. For stack PTEs, do this -- first allocating the page, making it invalid, then initializing the PFN, and then writing the valid page.

svn path=/trunk/; revision=47571

reactos/ntoskrnl/mm/ARM3/miarm.h
reactos/ntoskrnl/mm/ARM3/procsup.c

index a670bcd..8dd1698 100644 (file)
@@ -445,6 +445,29 @@ extern PFN_NUMBER MmSystemPageDirectory[PD_COUNT];
 #define MI_PFN_TO_PFNENTRY(x)     (&MmPfnDatabase[1][x])
 #define MI_PFNENTRY_TO_PFN(x)     (x - MmPfnDatabase[1])
 
+//
+// Creates a valid kernel PTE with the given protection
+//
+FORCEINLINE
+VOID
+MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte,
+                     IN PMMPTE MappingPte,
+                     IN ULONG ProtectionMask,
+                     IN PFN_NUMBER PageFrameNumber)
+{
+    /* Only valid for kernel, non-session PTEs */
+    ASSERT(MappingPte > MiHighestUserPte);
+    ASSERT(!MI_IS_SESSION_PTE(MappingPte));
+    ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP));
+    
+    /* Start fresh */
+    *NewPte = ValidKernelPte;
+    
+    /* Set the protection and page */
+    NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
+    NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
+}
+
 //
 // Returns if the page is physically resident (ie: a large page)
 // FIXFIX: CISC/x86 only?
index e82a567..551b685 100644 (file)
@@ -107,7 +107,7 @@ MmCreateKernelStack(IN BOOLEAN GuiStack,
     PFN_NUMBER StackPtes, StackPages;
     PMMPTE PointerPte, StackPte;
     PVOID BaseAddress;
-    MMPTE TempPte;
+    MMPTE TempPte, InvalidPte;
     KIRQL OldIrql;
     PFN_NUMBER PageFrameIndex;
     ULONG i;
@@ -151,13 +151,12 @@ MmCreateKernelStack(IN BOOLEAN GuiStack,
     if (GuiStack) PointerPte += BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE -
                                                KERNEL_LARGE_STACK_COMMIT);
     
-    //
-    // Setup the template stack PTE
-    //
-    TempPte = ValidKernelPte;
-    MI_MAKE_LOCAL_PAGE(&TempPte);
-    MI_MAKE_DIRTY_PAGE(&TempPte);
-    TempPte.u.Hard.PageFrameNumber = 0;
+
+    /* Setup the temporary invalid PTE */
+    MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS);
+
+    /* Setup the template stack PTE */
+    MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte + 1, MM_READWRITE, 0);
     
     //
     // Acquire the PFN DB lock
@@ -174,8 +173,10 @@ MmCreateKernelStack(IN BOOLEAN GuiStack,
         //
         PointerPte++;
         
-        /* Get a page */
+        /* Get a page and write the current invalid PTE */
         PageFrameIndex = MiRemoveAnyPage(0);
+        ASSERT(InvalidPte.u.Hard.Valid == 0);
+        *PointerPte = InvalidPte;
         
         /* Initialize the PFN entry for this page */
         MiInitializePfn(PageFrameIndex, PointerPte, 1);
@@ -210,7 +211,7 @@ MmGrowKernelStackEx(IN PVOID StackPointer,
     PMMPTE LimitPte, NewLimitPte, LastPte;
     PFN_NUMBER StackPages;
     KIRQL OldIrql;
-    MMPTE TempPte;
+    MMPTE TempPte, InvalidPte;
     PFN_NUMBER PageFrameIndex;
     
     //
@@ -251,13 +252,8 @@ MmGrowKernelStackEx(IN PVOID StackPointer,
     LimitPte--;
     StackPages = (LimitPte - NewLimitPte + 1);
     
-    //
-    // Setup the template stack PTE
-    //
-    TempPte = ValidKernelPte;
-    MI_MAKE_LOCAL_PAGE(&TempPte);
-    MI_MAKE_DIRTY_PAGE(&TempPte);
-    TempPte.u.Hard.PageFrameNumber = 0;
+    /* Setup the temporary invalid PTE */
+    MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS);
     
     //
     // Acquire the PFN DB lock
@@ -269,14 +265,18 @@ MmGrowKernelStackEx(IN PVOID StackPointer,
     //
     while (LimitPte >= NewLimitPte)
     {
-        /* Get a page */
+        /* Get a page and write the current invalid PTE */
         PageFrameIndex = MiRemoveAnyPage(0);
+        ASSERT(InvalidPte.u.Hard.Valid == 0);
+        *LimitPte = InvalidPte;
         
         /* Initialize the PFN entry for this page */
         MiInitializePfn(PageFrameIndex, LimitPte, 1);
         
+        /* Setup the template stack PTE */
+        MI_MAKE_HARDWARE_PTE(&TempPte, LimitPte, MM_READWRITE, PageFrameIndex);
+        
         /* Write the valid PTE */
-        TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
         ASSERT(LimitPte->u.Hard.Valid == 0);
         ASSERT(TempPte.u.Hard.Valid == 1);
         *LimitPte-- = TempPte;