[ros-diffs] [ros-arm-bringup] 32368: Review and fix the buildingg and mapping of boot-time kernel address space. The selection of the non-paged pool base address was broken (ion's comment was correct, but his implementation was not) -- NP pool now follows the PFN, or end of FreeLDR mapping area. There was no reason to put paged pool at a 4MB boundary away from NP pool -- it now follows it immediately. Got rid of multiple values which were calculated 3, even 4 times in a row, or even values that were calculated but never used (such as kernel_len). Got rid of the shuffling back and forth of kernel and virtual start/end addresses. A global now keeps track of this, and MmInit1 is now solely responsible for assigning addresses to each kernel region. Added new debug routine to show the kernel regions mapped -- enabled by default for now to visually detect any problems (once ReactOS's drivers go over 6MB, there may be).

ros-arm-bringup at svn.reactos.org ros-arm-bringup at svn.reactos.org
Fri Feb 15 00:39:32 CET 2008


Author: ros-arm-bringup
Date: Fri Feb 15 02:39:31 2008
New Revision: 32368

URL: http://svn.reactos.org/svn/reactos?rev=32368&view=rev
Log:
Review and fix the buildingg and mapping of boot-time kernel address space.
The selection of the non-paged pool base address was broken (ion's comment was correct, but his implementation was not) -- NP pool now follows the PFN, or end of FreeLDR mapping area.
There was no reason to put paged pool at a 4MB boundary away from NP pool -- it now follows it immediately.
Got rid of multiple values which were calculated 3, even 4 times in a row, or even values that were calculated but never used (such as kernel_len).
Got rid of the shuffling back and forth of kernel and virtual start/end addresses. A global now keeps track of this, and MmInit1 is now solely responsible for assigning addresses to each kernel region.
Added new debug routine to show the kernel regions mapped -- enabled by default for now to visually detect any problems (once ReactOS's drivers go over 6MB, there may be).

Modified:
    trunk/reactos/ntoskrnl/include/internal/mm.h
    trunk/reactos/ntoskrnl/ke/i386/kiinit.c
    trunk/reactos/ntoskrnl/mm/freelist.c
    trunk/reactos/ntoskrnl/mm/mminit.c

Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/mm.h?rev=32368&r1=32367&r2=32368&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/mm.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/mm.h Fri Feb 15 02:39:31 2008
@@ -17,6 +17,11 @@
 
 extern PVOID MmPagedPoolBase;
 extern ULONG MmPagedPoolSize;
+
+extern PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor;
+extern ULONG MmHighestPhysicalPage;
+extern PVOID MmPfnDatabase;
+extern ULONG_PTR MiKSeg0Start, MiKSeg0End;
 
 struct _KTRAP_FRAME;
 struct _EPROCESS;
@@ -260,6 +265,29 @@
     ULONG PagingRequestsInLastFiveMinutes;
     ULONG PagingRequestsInLastFifteenMinutes;
 } MM_STATS;
+
+typedef struct _PHYSICAL_PAGE
+{
+    union
+    {
+        struct
+        {
+            ULONG Type: 2;
+            ULONG Consumer: 3;
+            ULONG Zero: 1;
+        }
+        Flags;
+        ULONG AllFlags;
+    };
+    
+    LIST_ENTRY ListEntry;
+    ULONG ReferenceCount;
+    SWAPENTRY SavedSwapEntry;
+    ULONG LockCount;
+    ULONG MapCount;
+    struct _MM_RMAP_ENTRY* RmapListHead;
+}
+PHYSICAL_PAGE, *PPHYSICAL_PAGE;
 
 extern MM_STATS MmStats;
 
@@ -532,12 +560,8 @@
 VOID
 NTAPI
 MmInit1(
-    ULONG_PTR FirstKernelPhysAddress,
-    ULONG_PTR LastKernelPhysAddress,
-    ULONG_PTR LastKernelAddress,
     PADDRESS_RANGE BIOSMemoryMap,
-    ULONG AddressRangeCount,
-    ULONG MaxMemInMeg
+    ULONG AddressRangeCount
 );
 
 BOOLEAN
@@ -941,13 +965,9 @@
 NTAPI
 MmGetLockCountPage(PFN_TYPE Page);
 
-PVOID
+VOID
 NTAPI
 MmInitializePageList(
-    ULONG_PTR FirstPhysKernelAddress,
-    ULONG_PTR LastPhysKernelAddress,
-    ULONG MemorySizeInPages,
-    ULONG_PTR LastKernelBase,
     PADDRESS_RANGE BIOSMemoryMap,
     ULONG AddressRangeCount
 );

Modified: trunk/reactos/ntoskrnl/ke/i386/kiinit.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/kiinit.c?rev=32368&r1=32367&r2=32368&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/kiinit.c (original)
+++ trunk/reactos/ntoskrnl/ke/i386/kiinit.c Fri Feb 15 02:39:31 2008
@@ -537,12 +537,7 @@
     ((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess;
 
     /* Initialize Kernel Memory Address Space */
-    MmInit1(MmFreeLdrFirstKrnlPhysAddr,
-            MmFreeLdrLastKrnlPhysAddr,
-            MmFreeLdrLastKernelAddress,
-            KeMemoryMap,
-            KeMemoryMapRangeCount,
-            4096);
+    MmInit1(KeMemoryMap, KeMemoryMapRangeCount);
 
     /* Set basic CPU Features that user mode can read */
     SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =

Modified: trunk/reactos/ntoskrnl/mm/freelist.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/freelist.c?rev=32368&r1=32367&r2=32368&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/freelist.c (original)
+++ trunk/reactos/ntoskrnl/mm/freelist.c Fri Feb 15 02:39:31 2008
@@ -25,29 +25,6 @@
 #define MM_PHYSICAL_PAGE_FREE    (0x1)
 #define MM_PHYSICAL_PAGE_USED    (0x2)
 #define MM_PHYSICAL_PAGE_BIOS    (0x3)
-
-typedef struct _PHYSICAL_PAGE
-{
-   union
-   {
-      struct
-      {
-        ULONG Type: 2;
-        ULONG Consumer: 3;
-	ULONG Zero: 1;
-      }
-      Flags;
-      ULONG AllFlags;
-   };
-
-   LIST_ENTRY ListEntry;
-   ULONG ReferenceCount;
-   SWAPENTRY SavedSwapEntry;
-   ULONG LockCount;
-   ULONG MapCount;
-   struct _MM_RMAP_ENTRY* RmapListHead;
-}
-PHYSICAL_PAGE, *PPHYSICAL_PAGE;
 
 
 #define ASSERT_PFN(x) ASSERT((x)->Flags.Type != 0)
@@ -302,15 +279,9 @@
    return TRUE;
 }
 
-
-PVOID
-INIT_FUNCTION
-NTAPI
-MmInitializePageList(IN ULONG_PTR FirstPhysKernelAddress,
-                     IN ULONG_PTR LastPhysKernelAddress,
-                     IN ULONG HighestPage,
-                     IN ULONG_PTR LastKernelAddress,
-                     IN PADDRESS_RANGE BIOSMemoryMap,
+VOID
+NTAPI
+MmInitializePageList(IN PADDRESS_RANGE BIOSMemoryMap,
                      IN ULONG AddressRangeCount)
 {
     ULONG i;
@@ -318,11 +289,11 @@
     NTSTATUS Status;
     PFN_TYPE Pfn = 0;
     PHYSICAL_PAGE UsedPage;
-    extern PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor;
     ULONG PdeStart = PsGetCurrentProcess()->Pcb.DirectoryTableBase.LowPart;
     ULONG PdePageStart, PdePageEnd;
     ULONG VideoPageStart, VideoPageEnd;
     ULONG KernelPageStart, KernelPageEnd;
+    ULONG_PTR KernelStart, KernelEnd;
 
     /* Initialize the page lists */
     KeInitializeSpinLock(&PageListLock);
@@ -331,13 +302,9 @@
     InitializeListHead(&FreeZeroedPageListHead);
  
     /* Set the size and start of the PFN Database */
-    MmPageArraySize = HighestPage;
-    MmPageArray = (PHYSICAL_PAGE *)LastKernelAddress;
+    MmPageArray = (PHYSICAL_PAGE *)MmPfnDatabase;
+    MmPageArraySize = MmHighestPhysicalPage;
     Reserved = PAGE_ROUND_UP((MmPageArraySize * sizeof(PHYSICAL_PAGE))) / PAGE_SIZE;
-    
-    /* Update the last kernel address pointers */
-    LastKernelAddress = ((ULONG_PTR)LastKernelAddress + (Reserved * PAGE_SIZE));
-    LastPhysKernelAddress = (ULONG_PTR)LastPhysKernelAddress + (Reserved * PAGE_SIZE);
 
     /* Loop every page required to hold the PFN database */
     for (i = 0; i < Reserved; i++)
@@ -380,12 +347,14 @@
     UsedPage.MapCount = 1;
 
     /* We'll be applying a bunch of hacks -- precompute some static values */
+    KernelStart = MiKSeg0Start - KSEG0_BASE;
+    KernelEnd = MiKSeg0End - KSEG0_BASE;
     PdePageStart = PdeStart / PAGE_SIZE;
     PdePageEnd = MmFreeLdrPageDirectoryEnd / PAGE_SIZE;
     VideoPageStart = 0xA0000 / PAGE_SIZE;
     VideoPageEnd = 0x100000 / PAGE_SIZE;
-    KernelPageStart = FirstPhysKernelAddress / PAGE_SIZE;
-    KernelPageEnd = LastPhysKernelAddress / PAGE_SIZE;
+    KernelPageStart = KernelStart / PAGE_SIZE;
+    KernelPageEnd = KernelEnd / PAGE_SIZE;
     
     /* Loop every page on the system */
     for (i = 0; i <= MmPageArraySize; i++)
@@ -470,7 +439,6 @@
     
     MmStats.NrTotalPages = MmStats.NrFreePages + MmStats.NrSystemPages + MmStats.NrUserPages;
     MmInitializeBalancer(MmStats.NrFreePages, MmStats.NrSystemPages);
-    return((PVOID)LastKernelAddress);
 }
 
 VOID

Modified: trunk/reactos/ntoskrnl/mm/mminit.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/mminit.c?rev=32368&r1=32367&r2=32368&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/mminit.c (original)
+++ trunk/reactos/ntoskrnl/mm/mminit.c Fri Feb 15 02:39:31 2008
@@ -49,7 +49,10 @@
 PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress;
 PVOID MiNonPagedPoolStart;
 ULONG MiNonPagedPoolLength;
+ULONG MmBootImageSize;
 ULONG MmNumberOfPhysicalPages, MmHighestPhysicalPage, MmLowestPhysicalPage;
+ULONG_PTR MiKSeg0Start, MiKSeg0End;
+PVOID MmPfnDatabase;
 PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor;
 extern KMUTANT MmSystemLoadLock;
 BOOLEAN MiDbgEnableMdDump =
@@ -71,8 +74,7 @@
 VOID
 INIT_FUNCTION
 NTAPI
-MmInitVirtualMemory(ULONG_PTR LastKernelAddress,
-                    ULONG KernelLength)
+MmInitVirtualMemory()
 {
    PVOID BaseAddress;
    ULONG Length;
@@ -80,24 +82,9 @@
    PHYSICAL_ADDRESS BoundaryAddressMultiple;
    PMEMORY_AREA MArea;
 
-   DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress, KernelLength);
-
    BoundaryAddressMultiple.QuadPart = 0;
-   LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress);
 
    MmInitMemoryAreas();
-
-   /*
-    * FreeLDR Marks 6MB "in use" at the start of the kernel base,
-    * so start the non-paged pool at a boundary of 6MB from where
-    * the last driver was loaded. This should be the end of the
-    * FreeLDR-marked region.
-    */
-   MiNonPagedPoolStart = (PVOID)ROUND_UP((ULONG_PTR)LastKernelAddress + PAGE_SIZE, 0x600000);
-   MiNonPagedPoolLength = MM_NONPAGED_POOL_SIZE;
-
-   MmPagedPoolBase = (PVOID)ROUND_UP((ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength + PAGE_SIZE, 0x400000);
-   MmPagedPoolSize = MM_PAGED_POOL_SIZE;
 
    DPRINT("NonPagedPool %x - %x, PagedPool %x - %x\n", MiNonPagedPoolStart, (ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength - 1,
            MmPagedPoolBase, (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize - 1);
@@ -263,6 +250,32 @@
 
 VOID
 NTAPI
+MiDbgKernelLayout(VOID)
+{
+    DPRINT1("%8s%12s\t\t%s\n", "Start", "End", "Type");
+    DPRINT1("0x%p - 0x%p\t%s\n",
+            KSEG0_BASE, MiKSeg0Start,
+            "Undefined region");
+    DPRINT1("0x%p - 0x%p\t%s\n",
+            MiKSeg0Start, MmPfnDatabase,
+            "FreeLDR Kernel mapping region");
+    DPRINT1("0x%p - 0x%p\t%s\n",
+            MmPfnDatabase, MiKSeg0End,
+            "PFN Database region");
+    if (MiKSeg0End != (ULONG_PTR)MiNonPagedPoolStart)
+    DPRINT1("0x%p - 0x%p\t%s\n",
+            MiKSeg0End, MiNonPagedPoolStart,
+            "Remaining FreeLDR mapping");
+    DPRINT1("0x%p - 0x%p\t%s\n",
+             MiNonPagedPoolStart, (ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength,
+            "Non paged pool region");
+    DPRINT1("0x%p - 0x%p\t%s\n",
+            MmPagedPoolBase, (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize,
+            "Paged pool region");
+}
+
+VOID
+NTAPI
 MiDbgDumpBiosMap(IN PADDRESS_RANGE BIOSMemoryMap,
                  IN ULONG AddressRangeCount)
 {
@@ -306,7 +319,7 @@
     PLIST_ENTRY NextEntry;
     PMEMORY_ALLOCATION_DESCRIPTOR Md;
     ULONG_PTR LastKrnlPhysAddr = 0;
-        
+    
     for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
          NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
          NextEntry = NextEntry->Flink)
@@ -320,7 +333,7 @@
                 LastKrnlPhysAddr = Md->BasePage+Md->PageCount;   
         }
     }
-
+    
     /* Convert to a physical address */
     return LastKrnlPhysAddr << PAGE_SHIFT;
 }
@@ -328,16 +341,11 @@
 VOID
 INIT_FUNCTION
 NTAPI
-MmInit1(ULONG_PTR FirstKrnlPhysAddr,
-        ULONG_PTR LastKrnlPhysAddr,
-        ULONG_PTR LastKernelAddress,
-        PADDRESS_RANGE BIOSMemoryMap,
-        ULONG AddressRangeCount,
-        ULONG MaxMem)
-{
-    ULONG kernel_len;
+MmInit1(IN PADDRESS_RANGE BIOSMemoryMap,
+        IN ULONG AddressRangeCount)
+{
     PLDR_DATA_TABLE_ENTRY LdrEntry;
-
+    
     /* Dump memory descriptors */
     if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
     if (MiDbgEnableMdDump) MiDbgDumpBiosMap(BIOSMemoryMap, AddressRangeCount);
@@ -345,18 +353,9 @@
     /* Set the page directory */
     PsGetCurrentProcess()->Pcb.DirectoryTableBase.LowPart = (ULONG)MmGetPageDirectory();
 
-    /* NTLDR Hacks */
-    if (!MmFreeLdrPageDirectoryEnd) MmFreeLdrPageDirectoryEnd = 0x40000;
-
-    /* Get the first physical address */
-    LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink,
-                                 LDR_DATA_TABLE_ENTRY,
-                                 InLoadOrderLinks);
-    FirstKrnlPhysAddr = (ULONG_PTR)LdrEntry->DllBase - KSEG0_BASE;
-
-    /* Get the last kernel address */ 
-    LastKrnlPhysAddr = PAGE_ROUND_UP(MiGetLastKernelAddress());
-    LastKernelAddress = LastKrnlPhysAddr | KSEG0_BASE;
+    /* Get the size of FreeLDR's image allocations */
+    MmBootImageSize = KeLoaderBlock->Extension->LoaderPagesSpanned;
+    MmBootImageSize *= PAGE_SIZE;
 
     /* Set memory limits */
     MmSystemRangeStart = (PVOID)KSEG0_BASE;
@@ -377,21 +376,55 @@
     /* Initialize the kernel address space */
     MmInitializeKernelAddressSpace();
     MmInitGlobalKernelPageDirectory();
-
+    
+    /* Get kernel address boundaries */
+    LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink,
+                                 LDR_DATA_TABLE_ENTRY,
+                                 InLoadOrderLinks);
+    MiKSeg0Start = (ULONG_PTR)LdrEntry->DllBase | KSEG0_BASE;
+    MiKSeg0End = PAGE_ROUND_UP(MiGetLastKernelAddress()  | KSEG0_BASE);
+
+    /* We'll put the PFN array right after the loaded modules */
+    MmPfnDatabase = (PVOID)MiKSeg0End;
+    MiKSeg0End += MmHighestPhysicalPage * sizeof(PHYSICAL_PAGE);
+    MiKSeg0End = PAGE_ROUND_UP(MiKSeg0End);
+    
+    /*
+     * FreeLDR maps 6MB starting at the kernel base address, followed by the
+     * PFN database. If the PFN database doesn't go over the FreeLDR allocation
+     * then choose the end of the FreeLDR block. If it does go past the FreeLDR
+     * allocation, then choose the next PAGE_SIZE boundary.
+     */
+    if (MiKSeg0End < (MiKSeg0Start + 0x600000))
+    {
+        /* Use the first memory following FreeLDR's 6MB mapping */
+        MiNonPagedPoolStart = (PVOID)PAGE_ROUND_UP(MiKSeg0Start + 0x600000);
+    }
+    else
+    {
+        /* Use the next free available page */
+        MiNonPagedPoolStart = (PVOID)MiKSeg0End;
+    }
+    
+    /* Length of non-paged pool */
+    MiNonPagedPoolLength = MM_NONPAGED_POOL_SIZE;
+
+    /* Put the paged pool after the non-paged pool */
+    MmPagedPoolBase = (PVOID)PAGE_ROUND_UP((ULONG_PTR)MiNonPagedPoolStart +
+                                           MiNonPagedPoolLength);
+    MmPagedPoolSize = MM_PAGED_POOL_SIZE;
+    
+    /* Dump kernel memory layout */
+    MiDbgKernelLayout();
+    
     /* Initialize the page list */
-    LastKernelAddress = (ULONG_PTR)MmInitializePageList(FirstKrnlPhysAddr,
-                                                        LastKrnlPhysAddr,
-                                                        MmHighestPhysicalPage,
-                                                        PAGE_ROUND_UP(LastKernelAddress),
-                                                        BIOSMemoryMap,
-                                                        AddressRangeCount);
-    kernel_len = LastKrnlPhysAddr - FirstKrnlPhysAddr;
+    MmInitializePageList(BIOSMemoryMap, AddressRangeCount);
     
     /* Unmap low memory */
     MmDeletePageTable(NULL, 0);
 
     /* Intialize memory areas */
-    MmInitVirtualMemory(LastKernelAddress, kernel_len);
+    MmInitVirtualMemory();
 
     /* Initialize MDLs */
     MmInitializeMdlImplementation();




More information about the Ros-diffs mailing list