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/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@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?re... ============================================================================== --- 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=4... ============================================================================== --- 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@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.r... ============================================================================== --- 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>