[ros-diffs] [ros-arm-bringup] 41628: - Rewrite MmMapIoSpace and MmUnmapIoSpace to use System PTEs instead. - Much faster and cleaner (will be even faster when System PTE allocation is optimized). - Better handling of esoteric caching options, especially relevant for ARM. - Handled through the MiPlatformCacheAttributes, which should be defined differently for each platform (TODO). - Handles both I/O (device) and RAM physical memory. - Correct flushing of CPU caches (not a big deal on x86, but matters on ARM).

ros-arm-bringup at svn.reactos.org ros-arm-bringup at svn.reactos.org
Sun Jun 28 10:31:58 CEST 2009


Author: ros-arm-bringup
Date: Sat Jun 27 07:03:24 2009
New Revision: 41628

URL: http://svn.reactos.org/svn/reactos?rev=41628&view=rev
Log:
- Rewrite MmMapIoSpace and MmUnmapIoSpace to use System PTEs instead.
- Much faster and cleaner (will be even faster when System PTE allocation is optimized).
- Better handling of esoteric caching options, especially relevant for ARM.
  - Handled through the MiPlatformCacheAttributes, which should be defined differently for each platform (TODO).
    - Handles both I/O (device) and RAM physical memory.
- Correct flushing of CPU caches (not a big deal on x86, but matters on ARM).


Added:
    trunk/reactos/ntoskrnl/mm/ARM3/iosup.c
      - copied, changed from r41569, trunk/reactos/ntoskrnl/mm/iospace.c
Removed:
    trunk/reactos/ntoskrnl/mm/iospace.c
Modified:
    trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
    trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild

Copied: trunk/reactos/ntoskrnl/mm/ARM3/iosup.c (from r41569, trunk/reactos/ntoskrnl/mm/iospace.c)
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/iosup.c?p2=trunk/reactos/ntoskrnl/mm/ARM3/iosup.c&p1=trunk/reactos/ntoskrnl/mm/iospace.c&r1=41569&r2=41628&rev=41628&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/iospace.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/iosup.c [iso-8859-1] Sat Jun 27 07:03:24 2009
@@ -1,184 +1,257 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/mm/iospace.c
- * PURPOSE:         Mapping I/O space
- *
- * PROGRAMMERS:     David Welch (welch at mcmail.com)
- */
-
-/* INCLUDES *****************************************************************/
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            ntoskrnl/mm/ARM3/iosup.c
+ * PURPOSE:         ARM Memory Manager I/O Mapping Functionality
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
 
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <debug.h>
 
-/* FUNCTIONS *****************************************************************/
-
-/**********************************************************************
- * NAME       EXPORTED
- * MmMapIoSpace at 16
- *
- * DESCRIPTION
- *  Maps a physical memory range into system space.
- *
- * ARGUMENTS
- * PhysicalAddress
- *  First physical address to map;
- *
- * NumberOfBytes
- *  Number of bytes to map;
- *
- * CacheEnable
- *  Type of memory caching.
- *
- * RETURN VALUE
- * The base virtual address which maps the region.
- *
- * NOTE
- *  Description moved here from include/ddk/mmfuncs.h.
- *  Code taken from ntoskrnl/mm/special.c.
- *
- * REVISIONS
- *
- * @implemented
- */
-PVOID NTAPI
-MmMapIoSpace (IN PHYSICAL_ADDRESS PhysicalAddress,
-              IN ULONG NumberOfBytes,
-              IN MEMORY_CACHING_TYPE CacheEnable)
-{
-   PVOID Result;
-   ULONG Offset;
-   MEMORY_AREA* marea;
-   NTSTATUS Status;
-   ULONG i;
-   ULONG Protect;
-   PHYSICAL_ADDRESS BoundaryAddressMultiple;
-   PFN_TYPE Pfn;
-
-   DPRINT("MmMapIoSpace(%lx, %d, %d)\n", PhysicalAddress, NumberOfBytes, CacheEnable);
-
-   if (CacheEnable != MmNonCached &&
-       CacheEnable != MmCached &&
-       CacheEnable != MmWriteCombined)
-   {
-      return NULL;
-   }
-
-   BoundaryAddressMultiple.QuadPart = 0;
-   Result = NULL;
-   Offset = PhysicalAddress.u.LowPart % PAGE_SIZE;
-   NumberOfBytes += Offset;
-   PhysicalAddress.QuadPart -= Offset;
-   Protect = PAGE_EXECUTE_READWRITE | PAGE_SYSTEM;
-   if (CacheEnable != MmCached)
-   {
-      Protect |= (PAGE_NOCACHE | PAGE_WRITETHROUGH);
-   }
-
-   MmLockAddressSpace(MmGetKernelAddressSpace());
-   Status = MmCreateMemoryArea (MmGetKernelAddressSpace(),
-                                MEMORY_AREA_IO_MAPPING,
-                                &Result,
-                                NumberOfBytes,
-                                Protect,
-                                &marea,
-                                0,
-                                FALSE,
-                                BoundaryAddressMultiple);
-   MmUnlockAddressSpace(MmGetKernelAddressSpace());
-
-   if (!NT_SUCCESS(Status))
-   {
-      DPRINT("MmMapIoSpace failed (%lx)\n", Status);
-      return (NULL);
-   }
-   Pfn = PhysicalAddress.LowPart >> PAGE_SHIFT;
-   for (i = 0; i < PAGE_ROUND_UP(NumberOfBytes); i += PAGE_SIZE, Pfn++)
-   {
-      Status = MmCreateVirtualMappingForKernel((char*)Result + i,
-                                               Protect,
-                                               &Pfn,
-					       1);
-      if (!NT_SUCCESS(Status))
-      {
-         DbgPrint("Unable to create virtual mapping\n");
-         KeBugCheck(MEMORY_MANAGEMENT);
-      }
-   }
-   return (PVOID)((ULONG_PTR)Result + Offset);
-}
-
-
-/**********************************************************************
- * NAME       EXPORTED
- * MmUnmapIoSpace at 8
- *
- * DESCRIPTION
- *  Unmaps a physical memory range from system space.
- *
- * ARGUMENTS
- * BaseAddress
- *  The base virtual address which maps the region;
- *
- * NumberOfBytes
- *  Number of bytes to unmap.
- *
- * RETURN VALUE
- * None.
- *
- * NOTE
- *  Code taken from ntoskrnl/mm/special.c.
- *
- * REVISIONS
- *
- * @implemented
- */
-VOID NTAPI
-MmUnmapIoSpace (IN PVOID BaseAddress,
-                IN ULONG NumberOfBytes)
-{
-   LONG Offset;
-   PVOID Address = BaseAddress;
-
-   Offset = (ULONG_PTR)Address % PAGE_SIZE;
-   Address = RVA(Address, - Offset);
-   NumberOfBytes += Offset;
-
-   MmLockAddressSpace(MmGetKernelAddressSpace());
-   MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
-                         Address,
-                         NULL,
-                         NULL);
-   MmUnlockAddressSpace(MmGetKernelAddressSpace());
-}
-
-
-/**********************************************************************
- * NAME       EXPORTED
- * MmMapVideoDisplay at 16
- *
- * @implemented
- */
-PVOID NTAPI
-MmMapVideoDisplay (IN PHYSICAL_ADDRESS PhysicalAddress,
-                   IN ULONG   NumberOfBytes,
-                   IN MEMORY_CACHING_TYPE CacheType)
-{
-   return MmMapIoSpace (PhysicalAddress, NumberOfBytes, (BOOLEAN)CacheType);
-}
-
-
-/*
- * @implemented
- */
-VOID NTAPI
-MmUnmapVideoDisplay (IN PVOID BaseAddress,
-                     IN ULONG NumberOfBytes)
-{
-   MmUnmapIoSpace (BaseAddress, NumberOfBytes);
-}
-
+#line 15 "ARM³::IOSUP"
+#define MODULE_INVOLVED_IN_ARM3
+#include "../ARM3/miarm.h"
+
+/* GLOBALS ********************************************************************/
+
+//
+// Each architecture has its own caching attributes for both I/O and Physical
+// memory mappings.
+//
+// This describes the attributes for the x86 architecture. It eventually needs
+// to go in the appropriate i386 directory.
+//
+MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes[2][MmMaximumCacheType] =
+{
+    //
+    // RAM
+    //
+    {MiNonCached,MiCached,MiWriteCombined,MiCached,MiNonCached,MiWriteCombined},
+
+    //
+    // Device Memory
+    //
+    {MiNonCached,MiCached,MiWriteCombined,MiCached,MiNonCached,MiWriteCombined},
+};
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*
+ * @implemented
+ */
+PVOID
+NTAPI
+MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress,
+             IN ULONG NumberOfBytes,
+             IN MEMORY_CACHING_TYPE CacheType)
+{
+    
+    PFN_TYPE Pfn, PageCount;
+    PMMPTE PointerPte;
+    PVOID BaseAddress;
+    MMPTE TempPte;
+    PMMPFN Pfn1 = NULL;
+    MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
+    BOOLEAN IsIoMapping;
+    
+    //
+    // Normalize and validate the caching attributes
+    //
+    CacheType &= 0xFF;
+    if (CacheType >= MmMaximumCacheType) return NULL;
+    
+    //
+    // Calculate page count
+    //
+    PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(PhysicalAddress.LowPart,
+                                               NumberOfBytes);
+    
+    //
+    // Compute the PFN and check if it's a known I/O mapping
+    // Also translate the cache attribute
+    //
+    Pfn = (PFN_NUMBER)(PhysicalAddress.QuadPart >> PAGE_SHIFT);
+    IsIoMapping = (Pfn > MmHighestPhysicalPage) ? TRUE : FALSE;
+    if (!IsIoMapping) Pfn1 = MiGetPfnEntry(Pfn);
+    CacheAttribute = MiPlatformCacheAttributes[IsIoMapping][CacheType];
+    
+    //
+    // Now allocate system PTEs for the mapping, and get the VA
+    //
+    PointerPte = MiReserveSystemPtes(PageCount, SystemPteSpace);
+    if (!PointerPte) return NULL;
+    BaseAddress = MiPteToAddress(PointerPte);
+    
+    //
+    // Check if this is uncached
+    //
+    if (CacheAttribute != MiCached)
+    {
+        //
+        // Flush all caches
+        //
+        KeFlushEntireTb(TRUE, TRUE);
+        KeInvalidateAllCaches();
+    }
+    
+    //
+    // Now compute the VA offset
+    //
+    BaseAddress = (PVOID)((ULONG_PTR)BaseAddress +
+                          BYTE_OFFSET(PhysicalAddress.LowPart));
+    
+    //
+    // Get the template and configure caching
+    //
+    TempPte = HyperTemplatePte;
+    switch (CacheAttribute)
+    {
+        case MiNonCached:
+            
+            //
+            // Disable the cache
+            //
+            TempPte.u.Hard.CacheDisable = 1;
+            TempPte.u.Hard.WriteThrough = 1;
+            break;
+            
+        case MiCached:
+            
+            //
+            // Leave defaults
+            //
+            break;
+            
+        case MiWriteCombined:
+            
+            //
+            // We don't support write combining yet
+            //
+            ASSERT(FALSE);
+            break;
+            
+        default:
+            
+            //
+            // Should never happen
+            //
+            ASSERT(FALSE);
+            break;
+    }
+    
+    //
+    // Sanity check and re-flush
+    //
+    Pfn = (PFN_NUMBER)(PhysicalAddress.QuadPart >> PAGE_SHIFT);
+    ASSERT((Pfn1 == MiGetPfnEntry(Pfn)) || (Pfn1 == NULL));
+    KeFlushEntireTb(TRUE, TRUE);
+    KeInvalidateAllCaches();
+    
+    //
+    // Do the mapping
+    //
+    do
+    {
+        //
+        // Start out with nothing
+        //
+        ASSERT(PointerPte->u.Hard.Valid == 0);
+        
+        //
+        // Write the PFN
+        //
+        TempPte.u.Hard.PageFrameNumber = Pfn++;
+        *PointerPte++ = TempPte;
+    } while (--PageCount);
+    
+    //
+    // We're done!
+    //
+    return BaseAddress;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+MmUnmapIoSpace(IN PVOID BaseAddress,
+               IN ULONG NumberOfBytes)
+{    
+    PFN_NUMBER PageCount, Pfn;
+    PMMPTE PointerPte;
+    
+    //
+    // Sanity check
+    //
+    ASSERT(NumberOfBytes != 0);
+    
+    //
+    // Get the page count
+    //
+    PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, NumberOfBytes);
+    
+    //
+    // Get the PTE and PFN
+    //
+    PointerPte = MiAddressToPte(BaseAddress);
+    Pfn = PFN_FROM_PTE(PointerPte);
+    
+    //
+    // Is this an I/O mapping?
+    //
+    if (Pfn > MmHighestPhysicalPage)
+    {
+        //
+        // Destroy the PTE
+        //
+        RtlZeroMemory(PointerPte, PageCount * sizeof(MMPTE));
+        
+        //
+        // Blow the TLB
+        //
+        KeFlushEntireTb(TRUE, TRUE);
+    }
+    
+    //
+    // Release the PTEs
+    //
+    MiReleaseSystemPtes(PointerPte, PageCount, 0);
+}
+
+/*
+ * @implemented
+ */
+PVOID
+NTAPI
+MmMapVideoDisplay(IN PHYSICAL_ADDRESS PhysicalAddress,
+                  IN ULONG NumberOfBytes,
+                  IN MEMORY_CACHING_TYPE CacheType)
+{
+    PAGED_CODE();
+    
+    //
+    // Call the real function
+    //
+    return MmMapIoSpace(PhysicalAddress, NumberOfBytes, CacheType);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+MmUnmapVideoDisplay(IN PVOID BaseAddress,
+                    IN ULONG NumberOfBytes)
+{
+    //
+    // Call the real function
+    //
+    MmUnmapIoSpace(BaseAddress, NumberOfBytes);
+}
 
 /* EOF */

Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?rev=41628&r1=41627&r2=41628&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Sat Jun 27 07:03:24 2009
@@ -19,6 +19,14 @@
     NonPagedPoolExpansion,
     MaximumPtePoolTypes
 } MMSYSTEM_PTE_POOL_TYPE;
+
+typedef enum _MI_PFN_CACHE_ATTRIBUTE
+{
+    MiNonCached,
+    MiCached,
+    MiWriteCombined,
+    MiNotMapped
+} MI_PFN_CACHE_ATTRIBUTE, *PMI_PFN_CACHE_ATTRIBUTE;
 
 extern MMPTE HyperTemplatePte;
 
@@ -50,4 +58,12 @@
     IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
 );
 
+VOID
+NTAPI
+MiReleaseSystemPtes(
+    IN PMMPTE StartingPte,
+    IN ULONG NumberOfPtes,
+    IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
+);
+
 /* EOF */

Removed: trunk/reactos/ntoskrnl/mm/iospace.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/iospace.c?rev=41627&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/mm/iospace.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/iospace.c (removed)
@@ -1,184 +1,0 @@
-/*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/mm/iospace.c
- * PURPOSE:         Mapping I/O space
- *
- * PROGRAMMERS:     David Welch (welch at mcmail.com)
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <debug.h>
-
-/* FUNCTIONS *****************************************************************/
-
-/**********************************************************************
- * NAME       EXPORTED
- * MmMapIoSpace at 16
- *
- * DESCRIPTION
- *  Maps a physical memory range into system space.
- *
- * ARGUMENTS
- * PhysicalAddress
- *  First physical address to map;
- *
- * NumberOfBytes
- *  Number of bytes to map;
- *
- * CacheEnable
- *  Type of memory caching.
- *
- * RETURN VALUE
- * The base virtual address which maps the region.
- *
- * NOTE
- *  Description moved here from include/ddk/mmfuncs.h.
- *  Code taken from ntoskrnl/mm/special.c.
- *
- * REVISIONS
- *
- * @implemented
- */
-PVOID NTAPI
-MmMapIoSpace (IN PHYSICAL_ADDRESS PhysicalAddress,
-              IN ULONG NumberOfBytes,
-              IN MEMORY_CACHING_TYPE CacheEnable)
-{
-   PVOID Result;
-   ULONG Offset;
-   MEMORY_AREA* marea;
-   NTSTATUS Status;
-   ULONG i;
-   ULONG Protect;
-   PHYSICAL_ADDRESS BoundaryAddressMultiple;
-   PFN_TYPE Pfn;
-
-   DPRINT("MmMapIoSpace(%lx, %d, %d)\n", PhysicalAddress, NumberOfBytes, CacheEnable);
-
-   if (CacheEnable != MmNonCached &&
-       CacheEnable != MmCached &&
-       CacheEnable != MmWriteCombined)
-   {
-      return NULL;
-   }
-
-   BoundaryAddressMultiple.QuadPart = 0;
-   Result = NULL;
-   Offset = PhysicalAddress.u.LowPart % PAGE_SIZE;
-   NumberOfBytes += Offset;
-   PhysicalAddress.QuadPart -= Offset;
-   Protect = PAGE_EXECUTE_READWRITE | PAGE_SYSTEM;
-   if (CacheEnable != MmCached)
-   {
-      Protect |= (PAGE_NOCACHE | PAGE_WRITETHROUGH);
-   }
-
-   MmLockAddressSpace(MmGetKernelAddressSpace());
-   Status = MmCreateMemoryArea (MmGetKernelAddressSpace(),
-                                MEMORY_AREA_IO_MAPPING,
-                                &Result,
-                                NumberOfBytes,
-                                Protect,
-                                &marea,
-                                0,
-                                FALSE,
-                                BoundaryAddressMultiple);
-   MmUnlockAddressSpace(MmGetKernelAddressSpace());
-
-   if (!NT_SUCCESS(Status))
-   {
-      DPRINT("MmMapIoSpace failed (%lx)\n", Status);
-      return (NULL);
-   }
-   Pfn = PhysicalAddress.LowPart >> PAGE_SHIFT;
-   for (i = 0; i < PAGE_ROUND_UP(NumberOfBytes); i += PAGE_SIZE, Pfn++)
-   {
-      Status = MmCreateVirtualMappingForKernel((char*)Result + i,
-                                               Protect,
-                                               &Pfn,
-					       1);
-      if (!NT_SUCCESS(Status))
-      {
-         DbgPrint("Unable to create virtual mapping\n");
-         KeBugCheck(MEMORY_MANAGEMENT);
-      }
-   }
-   return (PVOID)((ULONG_PTR)Result + Offset);
-}
-
-
-/**********************************************************************
- * NAME       EXPORTED
- * MmUnmapIoSpace at 8
- *
- * DESCRIPTION
- *  Unmaps a physical memory range from system space.
- *
- * ARGUMENTS
- * BaseAddress
- *  The base virtual address which maps the region;
- *
- * NumberOfBytes
- *  Number of bytes to unmap.
- *
- * RETURN VALUE
- * None.
- *
- * NOTE
- *  Code taken from ntoskrnl/mm/special.c.
- *
- * REVISIONS
- *
- * @implemented
- */
-VOID NTAPI
-MmUnmapIoSpace (IN PVOID BaseAddress,
-                IN ULONG NumberOfBytes)
-{
-   LONG Offset;
-   PVOID Address = BaseAddress;
-
-   Offset = (ULONG_PTR)Address % PAGE_SIZE;
-   Address = RVA(Address, - Offset);
-   NumberOfBytes += Offset;
-
-   MmLockAddressSpace(MmGetKernelAddressSpace());
-   MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
-                         Address,
-                         NULL,
-                         NULL);
-   MmUnlockAddressSpace(MmGetKernelAddressSpace());
-}
-
-
-/**********************************************************************
- * NAME       EXPORTED
- * MmMapVideoDisplay at 16
- *
- * @implemented
- */
-PVOID NTAPI
-MmMapVideoDisplay (IN PHYSICAL_ADDRESS PhysicalAddress,
-                   IN ULONG   NumberOfBytes,
-                   IN MEMORY_CACHING_TYPE CacheType)
-{
-   return MmMapIoSpace (PhysicalAddress, NumberOfBytes, (BOOLEAN)CacheType);
-}
-
-
-/*
- * @implemented
- */
-VOID NTAPI
-MmUnmapVideoDisplay (IN PVOID BaseAddress,
-                     IN ULONG NumberOfBytes)
-{
-   MmUnmapIoSpace (BaseAddress, NumberOfBytes);
-}
-
-
-/* EOF */

Modified: trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild?rev=41628&r1=41627&r2=41628&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] Sat Jun 27 07:03:24 2009
@@ -362,6 +362,7 @@
 		<directory name="ARM3">
 			<file>hypermap.c</file>
 			<file>init.c</file>
+			<file>iosup.c</file>
 			<file>pool.c</file>
 			<file>syspte.c</file>
 		</directory>
@@ -371,7 +372,6 @@
 		<file>dbgpool.c</file>
 		<file>drvlck.c</file>
 		<file>freelist.c</file>
-		<file>iospace.c</file>
 		<file>kmap.c</file>
 		<file>marea.c</file>
 		<file>mdlsup.c</file>



More information about the Ros-diffs mailing list