From: Olivier Martin Date: Thu, 18 Jul 2013 06:20:33 +0000 (+0000) Subject: ArmPkg/CpuDxe: Moved memory mapping functions that are not architecture specific... X-Git-Tag: edk2-stable201903~12424 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=591fb3781aa5947ab05332463a22d3f660714fec ArmPkg/CpuDxe: Moved memory mapping functions that are not architecture specific to 'CpuMmuCommon.c' Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14482 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/ArmPkg/Drivers/CpuDxe/ArmV6/Mmu.c b/ArmPkg/Drivers/CpuDxe/ArmV6/Mmu.c index dcc7b682c0..2dbdb689fe 100644 --- a/ArmPkg/Drivers/CpuDxe/ArmV6/Mmu.c +++ b/ArmPkg/Drivers/CpuDxe/ArmV6/Mmu.c @@ -150,133 +150,6 @@ PageToGcdAttributes ( return EFI_SUCCESS; } -/** - Searches memory descriptors covered by given memory range. - - This function searches into the Gcd Memory Space for descriptors - (from StartIndex to EndIndex) that contains the memory range - specified by BaseAddress and Length. - - @param MemorySpaceMap Gcd Memory Space Map as array. - @param NumberOfDescriptors Number of descriptors in map. - @param BaseAddress BaseAddress for the requested range. - @param Length Length for the requested range. - @param StartIndex Start index into the Gcd Memory Space Map. - @param EndIndex End index into the Gcd Memory Space Map. - - @retval EFI_SUCCESS Search successfully. - @retval EFI_NOT_FOUND The requested descriptors does not exist. - -**/ -EFI_STATUS -SearchGcdMemorySpaces ( - IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap, - IN UINTN NumberOfDescriptors, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - OUT UINTN *StartIndex, - OUT UINTN *EndIndex - ) -{ - UINTN Index; - - *StartIndex = 0; - *EndIndex = 0; - for (Index = 0; Index < NumberOfDescriptors; Index++) { - if (BaseAddress >= MemorySpaceMap[Index].BaseAddress && - BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) { - *StartIndex = Index; - } - if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress && - BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) { - *EndIndex = Index; - return EFI_SUCCESS; - } - } - return EFI_NOT_FOUND; -} - - -/** - Sets the attributes for a specified range in Gcd Memory Space Map. - - This function sets the attributes for a specified range in - Gcd Memory Space Map. - - @param MemorySpaceMap Gcd Memory Space Map as array - @param NumberOfDescriptors Number of descriptors in map - @param BaseAddress BaseAddress for the range - @param Length Length for the range - @param Attributes Attributes to set - - @retval EFI_SUCCESS Memory attributes set successfully - @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space - -**/ -EFI_STATUS -SetGcdMemorySpaceAttributes ( - IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap, - IN UINTN NumberOfDescriptors, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes - ) -{ - EFI_STATUS Status; - UINTN Index; - UINTN StartIndex; - UINTN EndIndex; - EFI_PHYSICAL_ADDRESS RegionStart; - UINT64 RegionLength; - - // - // Get all memory descriptors covered by the memory range - // - Status = SearchGcdMemorySpaces ( - MemorySpaceMap, - NumberOfDescriptors, - BaseAddress, - Length, - &StartIndex, - &EndIndex - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Go through all related descriptors and set attributes accordingly - // - for (Index = StartIndex; Index <= EndIndex; Index++) { - if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) { - continue; - } - // - // Calculate the start and end address of the overlapping range - // - if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) { - RegionStart = BaseAddress; - } else { - RegionStart = MemorySpaceMap[Index].BaseAddress; - } - if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) { - RegionLength = BaseAddress + Length - RegionStart; - } else { - RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart; - } - // - // Set memory attributes according to MTRR attribute and the original attribute of descriptor - // - gDS->SetMemorySpaceAttributes ( - RegionStart, - RegionLength, - (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes) - ); - } - - return EFI_SUCCESS; -} - EFI_STATUS SyncCacheConfigPage ( IN UINT32 SectionIndex, @@ -824,121 +697,3 @@ SetMemoryAttributes ( return Status; } - - -/** - This function modifies the attributes for the memory region specified by BaseAddress and - Length from their current attributes to the attributes specified by Attributes. - - @param This The EFI_CPU_ARCH_PROTOCOL instance. - @param BaseAddress The physical address that is the start address of a memory region. - @param Length The size in bytes of the memory region. - @param Attributes The bit mask of attributes to set for the memory region. - - @retval EFI_SUCCESS The attributes were set for the memory region. - @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by - BaseAddress and Length cannot be modified. - @retval EFI_INVALID_PARAMETER Length is zero. - @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of - the memory resource range. - @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory - resource range specified by BaseAddress and Length. - The bit mask of attributes is not support for the memory resource - range specified by BaseAddress and Length. - -**/ -EFI_STATUS -EFIAPI -CpuSetMemoryAttributes ( - IN EFI_CPU_ARCH_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes - ) -{ - DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(%lx, %lx, %lx)\n", BaseAddress, Length, Attributes)); - if ( ((BaseAddress & ~TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK) != 0) || ((Length & ~TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK) != 0)){ - // minimum granularity is SIZE_4KB (4KB on ARM) - DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(%lx, %lx, %lx): minimum ganularity is SIZE_4KB\n", BaseAddress, Length, Attributes)); - return EFI_UNSUPPORTED; - } - - return SetMemoryAttributes (BaseAddress, Length, Attributes, 0); -} - - - -// -// Add a new protocol to support -// - -EFI_STATUS -EFIAPI -CpuConvertPagesToUncachedVirtualAddress ( - IN VIRTUAL_UNCACHED_PAGES_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS Address, - IN UINTN Length, - IN EFI_PHYSICAL_ADDRESS VirtualMask, - OUT UINT64 *Attributes OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; - - - if (Attributes != NULL) { - Status = gDS->GetMemorySpaceDescriptor (Address, &GcdDescriptor); - if (!EFI_ERROR (Status)) { - *Attributes = GcdDescriptor.Attributes; - } - } - - // - // Make this address range page fault if accessed. If it is a DMA buffer than this would - // be the PCI address. Code should always use the CPU address, and we will or in VirtualMask - // to that address. - // - Status = SetMemoryAttributes (Address, Length, EFI_MEMORY_WP, 0); - if (!EFI_ERROR (Status)) { - Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_UC, VirtualMask); - } - - DEBUG ((DEBUG_INFO | DEBUG_LOAD, "ConvertPagesToUncachedVirtualAddress()\n Unmapped 0x%08lx Mapped 0x%08lx 0x%x bytes\n", Address, Address | VirtualMask, Length)); - - return Status; -} - - -EFI_STATUS -EFIAPI -CpuReconvertPages ( - IN VIRTUAL_UNCACHED_PAGES_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS Address, - IN UINTN Length, - IN EFI_PHYSICAL_ADDRESS VirtualMask, - IN UINT64 Attributes - ) -{ - EFI_STATUS Status; - - DEBUG ((DEBUG_INFO | DEBUG_LOAD, "CpuReconvertPages(%lx, %x, %lx, %lx)\n", Address, Length, VirtualMask, Attributes)); - - // - // Unmap the alaised Address - // - Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_WP, 0); - if (!EFI_ERROR (Status)) { - // - // Restore atttributes - // - Status = SetMemoryAttributes (Address, Length, Attributes, 0); - } - - return Status; -} - - -VIRTUAL_UNCACHED_PAGES_PROTOCOL gVirtualUncachedPages = { - CpuConvertPagesToUncachedVirtualAddress, - CpuReconvertPages -}; diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.h b/ArmPkg/Drivers/CpuDxe/CpuDxe.h index 6349d8087f..7f59ca653c 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.h +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.h @@ -1,6 +1,7 @@ /** @file Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -139,6 +140,23 @@ PublishArmProcessorTable( VOID ); +EFI_STATUS +SetMemoryAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes, + IN EFI_PHYSICAL_ADDRESS VirtualMask + ); + +EFI_STATUS +SetGcdMemorySpaceAttributes ( + IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap, + IN UINTN NumberOfDescriptors, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + extern VIRTUAL_UNCACHED_PAGES_PROTOCOL gVirtualUncachedPages; #endif // __CPU_DXE_ARM_EXCEPTION_H__ diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf index 16afd0452d..6068a0fcec 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf @@ -3,7 +3,7 @@ # DXE CPU driver # # Copyright (c) 2009, Apple Inc. All rights reserved.
-# Copyright (c) 2011-2012, ARM Limited. All rights reserved. +# Copyright (c) 2011-2013, ARM Limited. All rights reserved. # # This program and the accompanying materials # are licensed and made available under the terms and conditions of the BSD License @@ -28,6 +28,7 @@ CpuDxe.c CpuDxe.h CpuMpCore.c + CpuMmuCommon.c # # Prior to ARMv6 we have multiple stacks, one per mode diff --git a/ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c b/ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c new file mode 100644 index 0000000000..b1364820a4 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c @@ -0,0 +1,256 @@ +/** @file +* +* Copyright (c) 2013, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include "CpuDxe.h" + +/** + Searches memory descriptors covered by given memory range. + + This function searches into the Gcd Memory Space for descriptors + (from StartIndex to EndIndex) that contains the memory range + specified by BaseAddress and Length. + + @param MemorySpaceMap Gcd Memory Space Map as array. + @param NumberOfDescriptors Number of descriptors in map. + @param BaseAddress BaseAddress for the requested range. + @param Length Length for the requested range. + @param StartIndex Start index into the Gcd Memory Space Map. + @param EndIndex End index into the Gcd Memory Space Map. + + @retval EFI_SUCCESS Search successfully. + @retval EFI_NOT_FOUND The requested descriptors does not exist. + +**/ +EFI_STATUS +SearchGcdMemorySpaces ( + IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap, + IN UINTN NumberOfDescriptors, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + OUT UINTN *StartIndex, + OUT UINTN *EndIndex + ) +{ + UINTN Index; + + *StartIndex = 0; + *EndIndex = 0; + for (Index = 0; Index < NumberOfDescriptors; Index++) { + if ((BaseAddress >= MemorySpaceMap[Index].BaseAddress) && + (BaseAddress < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length))) { + *StartIndex = Index; + } + if (((BaseAddress + Length - 1) >= MemorySpaceMap[Index].BaseAddress) && + ((BaseAddress + Length - 1) < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length))) { + *EndIndex = Index; + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + + +/** + Sets the attributes for a specified range in Gcd Memory Space Map. + + This function sets the attributes for a specified range in + Gcd Memory Space Map. + + @param MemorySpaceMap Gcd Memory Space Map as array + @param NumberOfDescriptors Number of descriptors in map + @param BaseAddress BaseAddress for the range + @param Length Length for the range + @param Attributes Attributes to set + + @retval EFI_SUCCESS Memory attributes set successfully + @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space + +**/ +EFI_STATUS +SetGcdMemorySpaceAttributes ( + IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap, + IN UINTN NumberOfDescriptors, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN StartIndex; + UINTN EndIndex; + EFI_PHYSICAL_ADDRESS RegionStart; + UINT64 RegionLength; + + DEBUG ((DEBUG_GCD, "SetGcdMemorySpaceAttributes[0x%lX; 0x%lX] = 0x%lX\n", + BaseAddress, BaseAddress + Length, Attributes)); + + // + // Get all memory descriptors covered by the memory range + // + Status = SearchGcdMemorySpaces ( + MemorySpaceMap, + NumberOfDescriptors, + BaseAddress, + Length, + &StartIndex, + &EndIndex + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Go through all related descriptors and set attributes accordingly + // + for (Index = StartIndex; Index <= EndIndex; Index++) { + if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) { + continue; + } + // + // Calculate the start and end address of the overlapping range + // + if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) { + RegionStart = BaseAddress; + } else { + RegionStart = MemorySpaceMap[Index].BaseAddress; + } + if ((BaseAddress + Length - 1) < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length)) { + RegionLength = BaseAddress + Length - RegionStart; + } else { + RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart; + } + // + // Set memory attributes according to MTRR attribute and the original attribute of descriptor + // + gDS->SetMemorySpaceAttributes ( + RegionStart, + RegionLength, + (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes) + ); + } + + return EFI_SUCCESS; +} + +/** + This function modifies the attributes for the memory region specified by BaseAddress and + Length from their current attributes to the attributes specified by Attributes. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param BaseAddress The physical address that is the start address of a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memory region. + + @retval EFI_SUCCESS The attributes were set for the memory region. + @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of + the memory resource range. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory + resource range specified by BaseAddress and Length. + The bit mask of attributes is not support for the memory resource + range specified by BaseAddress and Length. + +**/ +EFI_STATUS +EFIAPI +CpuSetMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +{ + DEBUG ((EFI_D_PAGE, "CpuSetMemoryAttributes(%lx, %lx, %lx)\n", BaseAddress, Length, Attributes)); + + if ((BaseAddress & (SIZE_4KB - 1)) != 0) { + // Minimum granularity is SIZE_4KB (4KB on ARM) + DEBUG ((EFI_D_PAGE, "CpuSetMemoryAttributes(%lx, %lx, %lx): Minimum ganularity is SIZE_4KB\n", BaseAddress, Length, Attributes)); + return EFI_UNSUPPORTED; + } + + return SetMemoryAttributes (BaseAddress, Length, Attributes, 0); +} + +EFI_STATUS +EFIAPI +CpuConvertPagesToUncachedVirtualAddress ( + IN VIRTUAL_UNCACHED_PAGES_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Address, + IN UINTN Length, + IN EFI_PHYSICAL_ADDRESS VirtualMask, + OUT UINT64 *Attributes OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; + + if (Attributes != NULL) { + Status = gDS->GetMemorySpaceDescriptor (Address, &GcdDescriptor); + if (!EFI_ERROR (Status)) { + *Attributes = GcdDescriptor.Attributes; + } + } + + // + // Make this address range page fault if accessed. If it is a DMA buffer than this would + // be the PCI address. Code should always use the CPU address, and we will or in VirtualMask + // to that address. + // + Status = SetMemoryAttributes (Address, Length, EFI_MEMORY_WP, 0); + if (!EFI_ERROR (Status)) { + Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_UC, VirtualMask); + } + + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "CpuConvertPagesToUncachedVirtualAddress()\n Unmapped 0x%08lx Mapped 0x%08lx 0x%x bytes\n", Address, Address | VirtualMask, Length)); + + return Status; +} + + +EFI_STATUS +EFIAPI +CpuReconvertPages ( + IN VIRTUAL_UNCACHED_PAGES_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Address, + IN UINTN Length, + IN EFI_PHYSICAL_ADDRESS VirtualMask, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "CpuReconvertPages(%lx, %x, %lx, %lx)\n", Address, Length, VirtualMask, Attributes)); + + // + // Unmap the aliased Address + // + Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_WP, 0); + if (!EFI_ERROR (Status)) { + // + // Restore atttributes + // + Status = SetMemoryAttributes (Address, Length, Attributes, 0); + } + + return Status; +} + + +VIRTUAL_UNCACHED_PAGES_PROTOCOL gVirtualUncachedPages = { + CpuConvertPagesToUncachedVirtualAddress, + CpuReconvertPages +};