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?p…
==============================================================================
--- 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(a)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@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@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@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?r…
==============================================================================
--- 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=…
==============================================================================
--- 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(a)mcmail.com)
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <debug.h>
-
-/* FUNCTIONS *****************************************************************/
-
-/**********************************************************************
- * NAME EXPORTED
- * MmMapIoSpace@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@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@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.…
==============================================================================
--- 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>