BOOLEAN InterruptState = FALSE;\r
EFI_HANDLE mCpuHandle = NULL;\r
BOOLEAN mIsFlushingGCD;\r
-UINT64 mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
-UINT64 mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;\r
+BOOLEAN mIsAllocatingPageTable = FALSE;\r
+UINT64 mValidMtrrAddressMask;\r
+UINT64 mValidMtrrBitsMask;\r
+UINT64 mTimerPeriod = 0;\r
\r
FIXED_MTRR mFixedMtrrTable[] = {\r
{\r
- MTRR_LIB_IA32_MTRR_FIX64K_00000,\r
+ MSR_IA32_MTRR_FIX64K_00000,\r
0,\r
0x10000\r
},\r
{\r
- MTRR_LIB_IA32_MTRR_FIX16K_80000,\r
+ MSR_IA32_MTRR_FIX16K_80000,\r
0x80000,\r
0x4000\r
},\r
{\r
- MTRR_LIB_IA32_MTRR_FIX16K_A0000,\r
+ MSR_IA32_MTRR_FIX16K_A0000,\r
0xA0000,\r
0x4000\r
},\r
{\r
- MTRR_LIB_IA32_MTRR_FIX4K_C0000,\r
+ MSR_IA32_MTRR_FIX4K_C0000,\r
0xC0000,\r
0x1000\r
},\r
{\r
- MTRR_LIB_IA32_MTRR_FIX4K_C8000,\r
+ MSR_IA32_MTRR_FIX4K_C8000,\r
0xC8000,\r
0x1000\r
},\r
{\r
- MTRR_LIB_IA32_MTRR_FIX4K_D0000,\r
+ MSR_IA32_MTRR_FIX4K_D0000,\r
0xD0000,\r
0x1000\r
},\r
{\r
- MTRR_LIB_IA32_MTRR_FIX4K_D8000,\r
+ MSR_IA32_MTRR_FIX4K_D8000,\r
0xD8000,\r
0x1000\r
},\r
{\r
- MTRR_LIB_IA32_MTRR_FIX4K_E0000,\r
+ MSR_IA32_MTRR_FIX4K_E0000,\r
0xE0000,\r
0x1000\r
},\r
{\r
- MTRR_LIB_IA32_MTRR_FIX4K_E8000,\r
+ MSR_IA32_MTRR_FIX4K_E8000,\r
0xE8000,\r
0x1000\r
},\r
{\r
- MTRR_LIB_IA32_MTRR_FIX4K_F0000,\r
+ MSR_IA32_MTRR_FIX4K_F0000,\r
0xF0000,\r
0x1000\r
},\r
{\r
- MTRR_LIB_IA32_MTRR_FIX4K_F8000,\r
+ MSR_IA32_MTRR_FIX4K_F8000,\r
0xF8000,\r
0x1000\r
},\r
OUT UINT64 *TimerPeriod OPTIONAL\r
)\r
{\r
+ UINT64 BeginValue;\r
+ UINT64 EndValue;\r
+\r
if (TimerValue == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
*TimerValue = AsmReadTsc ();\r
\r
if (TimerPeriod != NULL) {\r
+ if (mTimerPeriod == 0) {\r
+ //\r
+ // Read time stamp counter before and after delay of 100 microseconds\r
+ //\r
+ BeginValue = AsmReadTsc ();\r
+ MicroSecondDelay (100);\r
+ EndValue = AsmReadTsc ();\r
//\r
- // BugBug: Hard coded. Don't know how to do this generically\r
+ // Calculate the actual frequency\r
//\r
- *TimerPeriod = 1000000000;\r
+ mTimerPeriod = DivU64x64Remainder (\r
+ MultU64x32 (\r
+ 1000 * 1000 * 1000,\r
+ 100\r
+ ),\r
+ EndValue - BeginValue,\r
+ NULL\r
+ );\r
+ }\r
+ *TimerPeriod = mTimerPeriod;\r
}\r
\r
return EFI_SUCCESS;\r
// to avoid unnecessary computing.\r
//\r
if (mIsFlushingGCD) {\r
- DEBUG((EFI_D_INFO, " Flushing GCD\n"));\r
+ DEBUG((DEBUG_INFO, " 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
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
\r
PhysicalAddressBits = (UINT8) RegEax;\r
-\r
- mValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;\r
- mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;\r
} else {\r
- mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;\r
- mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
+ PhysicalAddressBits = 36;\r
}\r
+\r
+ mValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;\r
+ mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;\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
+ 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
IntersectionBase, IntersectionEnd - IntersectionBase,\r
Capabilities);\r
\r
- DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE,\r
+ DEBUG ((EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,\r
"%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName, __FUNCTION__,\r
IntersectionBase, IntersectionEnd, Status));\r
return Status;\r
}\r
\r
- DEBUG ((EFI_D_ERROR, "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "\r
+ DEBUG ((DEBUG_ERROR, "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "\r
"with aperture [%Lx, %Lx) cap %Lx\n", gEfiCallerBaseName, __FUNCTION__,\r
Descriptor->BaseAddress, Descriptor->BaseAddress + Descriptor->Length,\r
(UINT32)Descriptor->GcdMemoryType, Descriptor->Capabilities,\r
\r
Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "%a: %a: GetMemorySpaceMap(): %r\n",\r
+ DEBUG ((DEBUG_ERROR, "%a: %a: GetMemorySpaceMap(): %r\n",\r
gEfiCallerBaseName, __FUNCTION__, Status));\r
return Status;\r
}\r
Status = AddMemoryMappedIoSpace (BaseAddress, SIZE_4KB, EFI_MEMORY_UC);\r
ASSERT_EFI_ERROR (Status);\r
\r
+ //\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
Status = gDS->AllocateMemorySpace (\r
EfiGcdAllocateAddress,\r
EfiGcdMemoryTypeMemoryMappedIo,\r
ImageHandle,\r
NULL\r
);\r
- ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_INFO, "%a: %a: AllocateMemorySpace() Status - %r\n",\r
+ gEfiCallerBaseName, __FUNCTION__, Status));\r
+ }\r
}\r
\r
/**\r
//\r
InitInterruptDescriptorTable ();\r
\r
- //\r
- // Enable the local APIC for Virtual Wire Mode.\r
- //\r
- ProgramVirtualWireMode ();\r
-\r
//\r
// Install CPU Architectural Protocol\r
//\r