/** @file\r
CPU DXE Module to produce CPU ARCH Protocol.\r
\r
- Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
BOOLEAN InterruptState = FALSE;\r
EFI_HANDLE mCpuHandle = NULL;\r
BOOLEAN mIsFlushingGCD;\r
+BOOLEAN mIsAllocatingPageTable = FALSE;\r
UINT64 mValidMtrrAddressMask;\r
UINT64 mValidMtrrBitsMask;\r
UINT64 mTimerPeriod = 0;\r
// to avoid unnecessary computing.\r
//\r
if (mIsFlushingGCD) {\r
- DEBUG((DEBUG_INFO, " Flushing GCD\n"));\r
+ DEBUG((DEBUG_VERBOSE, " Flushing GCD\n"));\r
return EFI_SUCCESS;\r
}\r
\r
+ //\r
+ // During memory attributes updating, new pages may be allocated to setup\r
+ // smaller granularity of page table. Page allocation action might then cause\r
+ // another calling of CpuSetMemoryAttributes() recursively, due to memory\r
+ // protection policy configured (such as PcdDxeNxMemoryProtectionPolicy).\r
+ // Since this driver will always protect memory used as page table by itself,\r
+ // there's no need to apply protection policy requested from memory service.\r
+ // So it's safe to just return EFI_SUCCESS if this time of calling is caused\r
+ // by page table memory allocation.\r
+ //\r
+ if (mIsAllocatingPageTable) {\r
+ DEBUG((DEBUG_VERBOSE, " Allocating page table memory\n"));\r
+ return EFI_SUCCESS;\r
+ }\r
\r
CacheAttributes = Attributes & CACHE_ATTRIBUTE_MASK;\r
MemoryAttributes = Attributes & MEMORY_ATTRIBUTE_MASK;\r
//\r
// Set memory attribute by page table\r
//\r
- return AssignMemoryPageAttributes (NULL, BaseAddress, Length, MemoryAttributes, AllocatePages);\r
+ return AssignMemoryPageAttributes (NULL, BaseAddress, Length, MemoryAttributes, NULL);\r
}\r
\r
/**\r
\r
**/\r
VOID\r
-RefreshGcdMemoryAttributes (\r
+RefreshMemoryAttributesFromMtrr (\r
VOID\r
)\r
{\r
UINT32 FirmwareVariableMtrrCount;\r
UINT8 DefaultMemoryType;\r
\r
- if (!IsMtrrSupported ()) {\r
- return;\r
- }\r
-\r
FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
ASSERT (FirmwareVariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
\r
- mIsFlushingGCD = TRUE;\r
MemorySpaceMap = NULL;\r
\r
//\r
if (MemorySpaceMap != NULL) {\r
FreePool (MemorySpaceMap);\r
}\r
+}\r
\r
- //\r
- // Update page attributes\r
- //\r
- RefreshGcdMemoryAttributesFromPaging();\r
+/**\r
+ Check if paging is enabled or not.\r
+**/\r
+BOOLEAN\r
+IsPagingAndPageAddressExtensionsEnabled (\r
+ VOID\r
+ )\r
+{\r
+ IA32_CR0 Cr0;\r
+ IA32_CR4 Cr4;\r
+\r
+ Cr0.UintN = AsmReadCr0 ();\r
+ Cr4.UintN = AsmReadCr4 ();\r
+\r
+ return ((Cr0.Bits.PG != 0) && (Cr4.Bits.PAE != 0));\r
+}\r
+\r
+/**\r
+ Refreshes the GCD Memory Space attributes according to MTRRs and Paging.\r
+\r
+ This function refreshes the GCD Memory Space attributes according to MTRRs\r
+ and page tables.\r
+\r
+**/\r
+VOID\r
+RefreshGcdMemoryAttributes (\r
+ VOID\r
+ )\r
+{\r
+ mIsFlushingGCD = TRUE;\r
+\r
+ if (IsMtrrSupported ()) {\r
+ RefreshMemoryAttributesFromMtrr ();\r
+ }\r
+\r
+ if (IsPagingAndPageAddressExtensionsEnabled ()) {\r
+ RefreshGcdMemoryAttributesFromPaging ();\r
+ }\r
\r
mIsFlushingGCD = FALSE;\r
}\r
}\r
\r
/**\r
- Add and allocate CPU local APIC memory mapped space. \r
+ Add and allocate CPU local APIC memory mapped space.\r
\r
@param[in]ImageHandle Image handle this driver.\r
\r
ASSERT_EFI_ERROR (Status);\r
\r
//\r
- // Try to allocate APIC memory mapped space, does not check return \r
+ // Try to allocate APIC memory mapped space, does not check return\r
// status because it may be allocated by other driver, or DXE Core if\r
// this range is built into Memory Allocation HOB.\r
//\r
{\r
EFI_STATUS Status;\r
EFI_EVENT IdleLoopEvent;\r
- \r
+\r
InitializePageTableLib();\r
\r
InitializeFloatingPointUnits ();\r