/** @file\r
- CPU DXE Module.\r
+ CPU DXE Module to produce CPU ARCH Protocol.\r
\r
- Copyright (c) 2008 - 2010, 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
#include "CpuDxe.h"\r
+#include "CpuMp.h"\r
+#include "CpuPageTable.h"\r
\r
//\r
// Global Variables\r
//\r
-IA32_IDT_GATE_DESCRIPTOR gIdtTable[INTERRUPT_VECTOR_NUMBER] = { 0 };\r
-\r
-EFI_CPU_INTERRUPT_HANDLER ExternalVectorTable[0x100];\r
-BOOLEAN InterruptState = FALSE;\r
-EFI_HANDLE mCpuHandle = NULL;\r
-BOOLEAN mIsFlushingGCD;\r
-UINT8 mDefaultMemoryType = MTRR_CACHE_WRITE_BACK;\r
-UINT64 mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
-UINT64 mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;\r
-\r
-FIXED_MTRR mFixedMtrrTable[] = {\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
+\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
};\r
\r
-\r
EFI_CPU_ARCH_PROTOCOL gCpu = {\r
CpuFlushCpuDataCache,\r
CpuEnableInterrupt,\r
4 // DmaBufferAlignment\r
};\r
\r
-//\r
-// Error code flag indicating whether or not an error code will be\r
-// pushed on the stack if an exception occurs.\r
-//\r
-// 1 means an error code will be pushed, otherwise 0\r
-//\r
-// bit 0 - exception 0\r
-// bit 1 - exception 1\r
-// etc.\r
-//\r
-UINT32 mErrorCodeFlag = 0x00027d00;\r
-\r
//\r
// CPU Arch Protocol Functions\r
//\r
\r
-\r
-/**\r
- Common exception handler.\r
-\r
- @param InterruptType Exception type\r
- @param SystemContext EFI_SYSTEM_CONTEXT\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-CommonExceptionHandler (\r
- IN EFI_EXCEPTION_TYPE InterruptType,\r
- IN EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
-#if defined (MDE_CPU_IA32)\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "!!!! IA32 Exception Type - %08x !!!!\n",\r
- InterruptType\r
- ));\r
- if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "ExceptionData - %08x\n",\r
- SystemContext.SystemContextIa32->ExceptionData\r
- ));\r
- }\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "CS - %04x, EIP - %08x, EFL - %08x, SS - %04x\n",\r
- SystemContext.SystemContextIa32->Cs,\r
- SystemContext.SystemContextIa32->Eip,\r
- SystemContext.SystemContextIa32->Eflags,\r
- SystemContext.SystemContextIa32->Ss\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "DS - %04x, ES - %04x, FS - %04x, GS - %04x\n",\r
- SystemContext.SystemContextIa32->Ds,\r
- SystemContext.SystemContextIa32->Es,\r
- SystemContext.SystemContextIa32->Fs,\r
- SystemContext.SystemContextIa32->Gs\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "EAX - %08x, EBX - %08x, ECX - %08x, EDX - %08x\n",\r
- SystemContext.SystemContextIa32->Eax,\r
- SystemContext.SystemContextIa32->Ebx,\r
- SystemContext.SystemContextIa32->Ecx,\r
- SystemContext.SystemContextIa32->Edx\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",\r
- SystemContext.SystemContextIa32->Esp,\r
- SystemContext.SystemContextIa32->Ebp,\r
- SystemContext.SystemContextIa32->Esi,\r
- SystemContext.SystemContextIa32->Edi\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "GDT - %08x LIM - %04x, IDT - %08x LIM - %04x\n",\r
- SystemContext.SystemContextIa32->Gdtr[0],\r
- SystemContext.SystemContextIa32->Gdtr[1],\r
- SystemContext.SystemContextIa32->Idtr[0],\r
- SystemContext.SystemContextIa32->Idtr[1]\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "LDT - %08x, TR - %08x\n",\r
- SystemContext.SystemContextIa32->Ldtr,\r
- SystemContext.SystemContextIa32->Tr\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",\r
- SystemContext.SystemContextIa32->Cr0,\r
- SystemContext.SystemContextIa32->Cr2,\r
- SystemContext.SystemContextIa32->Cr3,\r
- SystemContext.SystemContextIa32->Cr4\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",\r
- SystemContext.SystemContextIa32->Dr0,\r
- SystemContext.SystemContextIa32->Dr1,\r
- SystemContext.SystemContextIa32->Dr2,\r
- SystemContext.SystemContextIa32->Dr3\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "DR6 - %08x, DR7 - %08x\n",\r
- SystemContext.SystemContextIa32->Dr6,\r
- SystemContext.SystemContextIa32->Dr7\r
- ));\r
-#elif defined (MDE_CPU_X64)\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "!!!! X64 Exception Type - %016lx !!!!\n",\r
- (UINT64)InterruptType\r
- ));\r
- if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "ExceptionData - %016lx\n",\r
- SystemContext.SystemContextX64->ExceptionData\r
- ));\r
- }\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "RIP - %016lx, RFL - %016lx\n",\r
- SystemContext.SystemContextX64->Rip,\r
- SystemContext.SystemContextX64->Rflags\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",\r
- SystemContext.SystemContextX64->Rax,\r
- SystemContext.SystemContextX64->Rcx,\r
- SystemContext.SystemContextX64->Rdx\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",\r
- SystemContext.SystemContextX64->Rbx,\r
- SystemContext.SystemContextX64->Rsp,\r
- SystemContext.SystemContextX64->Rbp\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "RSI - %016lx, RDI - %016lx\n",\r
- SystemContext.SystemContextX64->Rsi,\r
- SystemContext.SystemContextX64->Rdi\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",\r
- SystemContext.SystemContextX64->R8,\r
- SystemContext.SystemContextX64->R9,\r
- SystemContext.SystemContextX64->R10\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",\r
- SystemContext.SystemContextX64->R11,\r
- SystemContext.SystemContextX64->R12,\r
- SystemContext.SystemContextX64->R13\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "R14 - %016lx, R15 - %016lx\n",\r
- SystemContext.SystemContextX64->R14,\r
- SystemContext.SystemContextX64->R15\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "CS - %04lx, DS - %04lx, ES - %04lx, FS - %04lx, GS - %04lx, SS - %04lx\n",\r
- SystemContext.SystemContextX64->Cs,\r
- SystemContext.SystemContextX64->Ds,\r
- SystemContext.SystemContextX64->Es,\r
- SystemContext.SystemContextX64->Fs,\r
- SystemContext.SystemContextX64->Gs,\r
- SystemContext.SystemContextX64->Ss\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "GDT - %016lx; %04lx, IDT - %016lx; %04lx\n",\r
- SystemContext.SystemContextX64->Gdtr[0],\r
- SystemContext.SystemContextX64->Gdtr[1],\r
- SystemContext.SystemContextX64->Idtr[0],\r
- SystemContext.SystemContextX64->Idtr[1]\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "LDT - %016lx, TR - %016lx\n",\r
- SystemContext.SystemContextX64->Ldtr,\r
- SystemContext.SystemContextX64->Tr\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",\r
- SystemContext.SystemContextX64->Cr0,\r
- SystemContext.SystemContextX64->Cr2,\r
- SystemContext.SystemContextX64->Cr3\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "CR4 - %016lx, CR8 - %016lx\n",\r
- SystemContext.SystemContextX64->Cr4,\r
- SystemContext.SystemContextX64->Cr8\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",\r
- SystemContext.SystemContextX64->Dr0,\r
- SystemContext.SystemContextX64->Dr1,\r
- SystemContext.SystemContextX64->Dr2\r
- ));\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",\r
- SystemContext.SystemContextX64->Dr3,\r
- SystemContext.SystemContextX64->Dr6,\r
- SystemContext.SystemContextX64->Dr7\r
- ));\r
-#else\r
-#error CPU type not supported for exception information dump!\r
-#endif\r
-\r
- //\r
- // Hang the system with CpuSleep so the processor will enter a lower power\r
- // state.\r
- //\r
- while (TRUE) {\r
- CpuSleep ();\r
- };\r
-}\r
-\r
-\r
/**\r
Flush CPU data cache. If the instruction cache is fully coherent\r
with all DMA operations then function can just return EFI_SUCCESS.\r
EFI_STATUS\r
EFIAPI\r
CpuFlushCpuDataCache (\r
- IN EFI_CPU_ARCH_PROTOCOL *This,\r
- IN EFI_PHYSICAL_ADDRESS Start,\r
- IN UINT64 Length,\r
- IN EFI_CPU_FLUSH_TYPE FlushType\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS Start,\r
+ IN UINT64 Length,\r
+ IN EFI_CPU_FLUSH_TYPE FlushType\r
)\r
{\r
if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {\r
}\r
}\r
\r
-\r
/**\r
Enables CPU interrupts.\r
\r
EFI_STATUS\r
EFIAPI\r
CpuEnableInterrupt (\r
- IN EFI_CPU_ARCH_PROTOCOL *This\r
+ IN EFI_CPU_ARCH_PROTOCOL *This\r
)\r
{\r
EnableInterrupts ();\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
Disables CPU interrupts.\r
\r
EFI_STATUS\r
EFIAPI\r
CpuDisableInterrupt (\r
- IN EFI_CPU_ARCH_PROTOCOL *This\r
+ IN EFI_CPU_ARCH_PROTOCOL *This\r
)\r
{\r
DisableInterrupts ();\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
Return the state of interrupts.\r
\r
EFI_STATUS\r
EFIAPI\r
CpuGetInterruptState (\r
- IN EFI_CPU_ARCH_PROTOCOL *This,\r
- OUT BOOLEAN *State\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ OUT BOOLEAN *State\r
)\r
{\r
if (State == NULL) {\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
Generates an INIT to the CPU.\r
\r
EFI_STATUS\r
EFIAPI\r
CpuInit (\r
- IN EFI_CPU_ARCH_PROTOCOL *This,\r
- IN EFI_CPU_INIT_TYPE InitType\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_CPU_INIT_TYPE InitType\r
)\r
{\r
return EFI_UNSUPPORTED;\r
}\r
\r
-\r
/**\r
Registers a function to be called from the CPU interrupt handler.\r
\r
EFI_STATUS\r
EFIAPI\r
CpuRegisterInterruptHandler (\r
- IN EFI_CPU_ARCH_PROTOCOL *This,\r
- IN EFI_EXCEPTION_TYPE InterruptType,\r
- IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_EXCEPTION_TYPE InterruptType,\r
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
)\r
{\r
- if (InterruptType < 0 || InterruptType > 0xff) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- if (InterruptHandler == NULL && ExternalVectorTable[InterruptType] == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (InterruptHandler != NULL && ExternalVectorTable[InterruptType] != NULL) {\r
- return EFI_ALREADY_STARTED;\r
- }\r
-\r
- ExternalVectorTable[InterruptType] = InterruptHandler;\r
- return EFI_SUCCESS;\r
+ return RegisterCpuInterruptHandler (InterruptType, InterruptHandler);\r
}\r
\r
-\r
/**\r
Returns a timer value from one of the CPU's internal timers. There is no\r
inherent time interval between ticks but is a function of the CPU frequency.\r
EFI_STATUS\r
EFIAPI\r
CpuGetTimerValue (\r
- IN EFI_CPU_ARCH_PROTOCOL *This,\r
- IN UINT32 TimerIndex,\r
- OUT UINT64 *TimerValue,\r
- OUT UINT64 *TimerPeriod OPTIONAL\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN UINT32 TimerIndex,\r
+ OUT UINT64 *TimerValue,\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
- // BugBug: Hard coded. Don't know how to do this generically\r
+ BeginValue = AsmReadTsc ();\r
+ MicroSecondDelay (100);\r
+ EndValue = AsmReadTsc ();\r
//\r
- *TimerPeriod = 1000000000;\r
+ // Calculate the actual frequency\r
+ //\r
+ mTimerPeriod = DivU64x64Remainder (\r
+ MultU64x32 (\r
+ 1000 * 1000 * 1000,\r
+ 100\r
+ ),\r
+ EndValue - BeginValue,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ *TimerPeriod = mTimerPeriod;\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
- Set memory cacheability attributes for given range of memeory.\r
+ A minimal wrapper function that allows MtrrSetAllMtrrs() to be passed to\r
+ EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() as Procedure.\r
\r
- @param This Protocol instance structure\r
- @param BaseAddress Specifies the start address of the\r
- memory range\r
- @param Length Specifies the length of the memory range\r
- @param Attributes The memory cacheability for the memory range\r
+ @param[in] Buffer Pointer to an MTRR_SETTINGS object, to be passed to\r
+ MtrrSetAllMtrrs().\r
+**/\r
+VOID\r
+EFIAPI\r
+SetMtrrsFromBuffer (\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ MtrrSetAllMtrrs (Buffer);\r
+}\r
\r
- @retval EFI_SUCCESS If the cacheability of that memory range is\r
- set successfully\r
- @retval EFI_UNSUPPORTED If the desired operation cannot be done\r
- @retval EFI_INVALID_PARAMETER The input parameter is not correct,\r
- such as Length = 0\r
+/**\r
+ Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.\r
+\r
+ This function modifies the attributes for the memory region specified by BaseAddress and\r
+ Length from their current attributes to the attributes specified by Attributes.\r
+\r
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.\r
+ @param BaseAddress The physical address that is the start address of a memory region.\r
+ @param Length The size in bytes of the memory region.\r
+ @param Attributes The bit mask of attributes to set for the memory region.\r
+\r
+ @retval EFI_SUCCESS The attributes were set for the memory region.\r
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
+ BaseAddress and Length cannot be modified.\r
+ @retval EFI_INVALID_PARAMETER Length is zero.\r
+ Attributes specified an illegal combination of attributes that\r
+ cannot be set together.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
+ the memory resource range.\r
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
+ resource range specified by BaseAddress and Length.\r
+ The bit mask of attributes is not support for the memory resource\r
+ range specified by BaseAddress and Length.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
CpuSetMemoryAttributes (\r
- IN EFI_CPU_ARCH_PROTOCOL *This,\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- IN UINT64 Attributes\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes\r
)\r
{\r
RETURN_STATUS Status;\r
MTRR_MEMORY_CACHE_TYPE CacheType;\r
-\r
- if (!IsMtrrSupported ()) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- DEBUG((EFI_D_ERROR, "CpuAp: SetMemorySpaceAttributes(BA=%08x, Len=%08x, Attr=%08x)\n", BaseAddress, Length, Attributes));\r
+ EFI_STATUS MpStatus;\r
+ EFI_MP_SERVICES_PROTOCOL *MpService;\r
+ MTRR_SETTINGS MtrrSettings;\r
+ UINT64 CacheAttributes;\r
+ UINT64 MemoryAttributes;\r
+ MTRR_MEMORY_CACHE_TYPE CurrentCacheType;\r
\r
//\r
// If this function is called because GCD SetMemorySpaceAttributes () is called\r
- // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory\r
+ // by RefreshGcdMemoryAttributes (), then we are just synchronizing GCD memory\r
// map with MTRR values. So there is no need to modify MTRRs, just return immediately\r
// to avoid unnecessary computing.\r
//\r
if (mIsFlushingGCD) {\r
- DEBUG((EFI_D_ERROR, " Flushing GCD\n"));\r
- return EFI_SUCCESS;\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 & EFI_CACHE_ATTRIBUTE_MASK;\r
+ MemoryAttributes = Attributes & EFI_MEMORY_ATTRIBUTE_MASK;\r
+\r
+ if (Attributes != (CacheAttributes | MemoryAttributes)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (CacheAttributes != 0) {\r
+ if (!IsMtrrSupported ()) {\r
+ return EFI_UNSUPPORTED;\r
}\r
\r
- switch (Attributes) {\r
- case EFI_MEMORY_UC:\r
- CacheType = CacheUncacheable;\r
- break;\r
+ switch (CacheAttributes) {\r
+ case EFI_MEMORY_UC:\r
+ CacheType = CacheUncacheable;\r
+ break;\r
\r
- case EFI_MEMORY_WC:\r
- CacheType = CacheWriteCombining;\r
- break;\r
+ case EFI_MEMORY_WC:\r
+ CacheType = CacheWriteCombining;\r
+ break;\r
\r
- case EFI_MEMORY_WT:\r
- CacheType = CacheWriteThrough;\r
- break;\r
+ case EFI_MEMORY_WT:\r
+ CacheType = CacheWriteThrough;\r
+ break;\r
\r
- case EFI_MEMORY_WP:\r
- CacheType = CacheWriteProtected;\r
- break;\r
+ case EFI_MEMORY_WP:\r
+ CacheType = CacheWriteProtected;\r
+ break;\r
\r
- case EFI_MEMORY_WB:\r
- CacheType = CacheWriteBack;\r
- break;\r
+ case EFI_MEMORY_WB:\r
+ CacheType = CacheWriteBack;\r
+ break;\r
\r
- default:\r
- return EFI_UNSUPPORTED;\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CurrentCacheType = MtrrGetMemoryAttribute (BaseAddress);\r
+ if (CurrentCacheType != CacheType) {\r
+ //\r
+ // call MTRR library function\r
+ //\r
+ Status = MtrrSetMemoryAttribute (\r
+ BaseAddress,\r
+ Length,\r
+ CacheType\r
+ );\r
+\r
+ if (!RETURN_ERROR (Status)) {\r
+ MpStatus = gBS->LocateProtocol (\r
+ &gEfiMpServiceProtocolGuid,\r
+ NULL,\r
+ (VOID **)&MpService\r
+ );\r
+ //\r
+ // Synchronize the update with all APs\r
+ //\r
+ if (!EFI_ERROR (MpStatus)) {\r
+ MtrrGetAllMtrrs (&MtrrSettings);\r
+ MpStatus = MpService->StartupAllAPs (\r
+ MpService, // This\r
+ SetMtrrsFromBuffer, // Procedure\r
+ FALSE, // SingleThread\r
+ NULL, // WaitEvent\r
+ 0, // TimeoutInMicrosecsond\r
+ &MtrrSettings, // ProcedureArgument\r
+ NULL // FailedCpuList\r
+ );\r
+ ASSERT (MpStatus == EFI_SUCCESS || MpStatus == EFI_NOT_STARTED);\r
+ }\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
}\r
+\r
//\r
- // call MTRR libary function\r
+ // Set memory attribute by page table\r
//\r
- DEBUG((EFI_D_ERROR, " MtrrSetMemoryAttribute()\n"));\r
- Status = MtrrSetMemoryAttribute(\r
- BaseAddress,\r
- Length,\r
- CacheType\r
- );\r
-\r
- MtrrDebugPrintAllMtrrs ();\r
-\r
- return (EFI_STATUS) Status;\r
+ return AssignMemoryPageAttributes (NULL, BaseAddress, Length, MemoryAttributes, NULL);\r
}\r
\r
/**\r
VOID\r
)\r
{\r
- UINT32 RegEax;\r
- UINT8 PhysicalAddressBits;\r
+ UINT32 RegEax;\r
+ UINT8 PhysicalAddressBits;\r
\r
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
\r
if (RegEax >= 0x80000008) {\r
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
\r
- PhysicalAddressBits = (UINT8) RegEax;\r
-\r
- mValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;\r
- mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;\r
+ PhysicalAddressBits = (UINT8)RegEax;\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
UINT64\r
GetMemorySpaceAttributeFromMtrrType (\r
- IN UINT8 MtrrAttributes\r
+ IN UINT8 MtrrAttributes\r
)\r
{\r
switch (MtrrAttributes) {\r
- case MTRR_CACHE_UNCACHEABLE:\r
- return EFI_MEMORY_UC;\r
- case MTRR_CACHE_WRITE_COMBINING:\r
- return EFI_MEMORY_WC;\r
- case MTRR_CACHE_WRITE_THROUGH:\r
- return EFI_MEMORY_WT;\r
- case MTRR_CACHE_WRITE_PROTECTED:\r
- return EFI_MEMORY_WP;\r
- case MTRR_CACHE_WRITE_BACK:\r
- return EFI_MEMORY_WB;\r
- default:\r
- return 0;\r
+ case MTRR_CACHE_UNCACHEABLE:\r
+ return EFI_MEMORY_UC;\r
+ case MTRR_CACHE_WRITE_COMBINING:\r
+ return EFI_MEMORY_WC;\r
+ case MTRR_CACHE_WRITE_THROUGH:\r
+ return EFI_MEMORY_WT;\r
+ case MTRR_CACHE_WRITE_PROTECTED:\r
+ return EFI_MEMORY_WP;\r
+ case MTRR_CACHE_WRITE_BACK:\r
+ return EFI_MEMORY_WB;\r
+ default:\r
+ return 0;\r
}\r
}\r
\r
**/\r
EFI_STATUS\r
SearchGcdMemorySpaces (\r
- IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
- IN UINTN NumberOfDescriptors,\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- OUT UINTN *StartIndex,\r
- OUT UINTN *EndIndex\r
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
+ IN UINTN NumberOfDescriptors,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ OUT UINTN *StartIndex,\r
+ OUT UINTN *EndIndex\r
)\r
{\r
- UINTN Index;\r
+ UINTN Index;\r
\r
*StartIndex = 0;\r
*EndIndex = 0;\r
for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
- if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&\r
- BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
+ if ((BaseAddress >= MemorySpaceMap[Index].BaseAddress) &&\r
+ (BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length))\r
+ {\r
*StartIndex = Index;\r
}\r
- if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&\r
- BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
+\r
+ if ((BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress) &&\r
+ (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length))\r
+ {\r
*EndIndex = Index;\r
return EFI_SUCCESS;\r
}\r
}\r
+\r
return EFI_NOT_FOUND;\r
}\r
\r
**/\r
EFI_STATUS\r
SetGcdMemorySpaceAttributes (\r
- IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
- IN UINTN NumberOfDescriptors,\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- IN UINT64 Attributes\r
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
+ IN UINTN NumberOfDescriptors,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes\r
)\r
{\r
EFI_STATUS Status;\r
if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
continue;\r
}\r
+\r
//\r
// Calculate the start and end address of the overlapping range\r
//\r
} else {\r
RegionStart = MemorySpaceMap[Index].BaseAddress;\r
}\r
+\r
if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
RegionLength = BaseAddress + Length - RegionStart;\r
} else {\r
RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;\r
}\r
+\r
//\r
// Set memory attributes according to MTRR attribute and the original attribute of descriptor\r
//\r
gDS->SetMemorySpaceAttributes (\r
RegionStart,\r
RegionLength,\r
- (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)\r
+ (MemorySpaceMap[Index].Attributes & ~EFI_CACHE_ATTRIBUTE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)\r
);\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
Refreshes the GCD Memory Space attributes according to MTRRs.\r
\r
\r
**/\r
VOID\r
-RefreshGcdMemoryAttributes (\r
+RefreshMemoryAttributesFromMtrr (\r
VOID\r
)\r
{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- UINTN SubIndex;\r
- UINT64 RegValue;\r
- EFI_PHYSICAL_ADDRESS BaseAddress;\r
- UINT64 Length;\r
- UINT64 Attributes;\r
- UINT64 CurrentAttributes;\r
- UINT8 MtrrType;\r
- UINTN NumberOfDescriptors;\r
- EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
- UINT64 DefaultAttributes;\r
- VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
- MTRR_FIXED_SETTINGS MtrrFixedSettings;\r
- UINT32 FirmwareVariableMtrrCount;\r
-\r
- if (!IsMtrrSupported ()) {\r
- return;\r
- }\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN SubIndex;\r
+ UINT64 RegValue;\r
+ EFI_PHYSICAL_ADDRESS BaseAddress;\r
+ UINT64 Length;\r
+ UINT64 Attributes;\r
+ UINT64 CurrentAttributes;\r
+ UINT8 MtrrType;\r
+ UINTN NumberOfDescriptors;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
+ UINT64 DefaultAttributes;\r
+ VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
+ MTRR_FIXED_SETTINGS MtrrFixedSettings;\r
+ UINT32 FirmwareVariableMtrrCount;\r
+ UINT8 DefaultMemoryType;\r
\r
FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
ASSERT (FirmwareVariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
\r
-// mIsFlushingGCD = TRUE;\r
- mIsFlushingGCD = FALSE;\r
MemorySpaceMap = NULL;\r
\r
//\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (mDefaultMemoryType);\r
+ DefaultMemoryType = (UINT8)MtrrGetDefaultMemoryType ();\r
+ DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType);\r
\r
//\r
// Set default attributes to all spaces.\r
if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
continue;\r
}\r
+\r
gDS->SetMemorySpaceAttributes (\r
MemorySpaceMap[Index].BaseAddress,\r
MemorySpaceMap[Index].Length,\r
- (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) |\r
+ (MemorySpaceMap[Index].Attributes & ~EFI_CACHE_ATTRIBUTE_MASK) |\r
(MemorySpaceMap[Index].Capabilities & DefaultAttributes)\r
);\r
}\r
//\r
for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
if (VariableMtrr[Index].Valid &&\r
- VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) {\r
+ (VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK))\r
+ {\r
SetGcdMemorySpaceAttributes (\r
MemorySpaceMap,\r
NumberOfDescriptors,\r
);\r
}\r
}\r
+\r
//\r
- // Go for variable MTRRs with Non-WB attribute\r
+ // Go for variable MTRRs with the attribute except for WB and UC attributes\r
//\r
for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
if (VariableMtrr[Index].Valid &&\r
- VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK) {\r
- Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8) VariableMtrr[Index].Type);\r
+ (VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK) &&\r
+ (VariableMtrr[Index].Type != MTRR_CACHE_UNCACHEABLE))\r
+ {\r
+ Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8)VariableMtrr[Index].Type);\r
SetGcdMemorySpaceAttributes (\r
MemorySpaceMap,\r
NumberOfDescriptors,\r
}\r
}\r
\r
+ //\r
+ // Go for variable MTRRs with UC attribute\r
+ //\r
+ for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
+ if (VariableMtrr[Index].Valid &&\r
+ (VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE))\r
+ {\r
+ SetGcdMemorySpaceAttributes (\r
+ MemorySpaceMap,\r
+ NumberOfDescriptors,\r
+ VariableMtrr[Index].BaseAddress,\r
+ VariableMtrr[Index].Length,\r
+ EFI_MEMORY_UC\r
+ );\r
+ }\r
+ }\r
+\r
//\r
// Go for fixed MTRRs\r
//\r
// Check for continuous fixed MTRR sections\r
//\r
for (SubIndex = 0; SubIndex < 8; SubIndex++) {\r
- MtrrType = (UINT8) RShiftU64 (RegValue, SubIndex * 8);\r
+ MtrrType = (UINT8)RShiftU64 (RegValue, SubIndex * 8);\r
CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);\r
if (Length == 0) {\r
//\r
Attributes = CurrentAttributes;\r
} else {\r
//\r
- // If fixed MTRR attribute changed, then set memory attribute for previous atrribute\r
+ // If fixed MTRR attribute changed, then set memory attribute for previous attribute\r
//\r
if (CurrentAttributes != Attributes) {\r
SetGcdMemorySpaceAttributes (\r
Attributes\r
);\r
BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;\r
- Length = 0;\r
- Attributes = CurrentAttributes;\r
+ Length = 0;\r
+ Attributes = CurrentAttributes;\r
}\r
}\r
+\r
Length += mFixedMtrrTable[Index].Length;\r
}\r
}\r
+\r
//\r
// Handle the last fixed MTRR region\r
//\r
if (MemorySpaceMap != NULL) {\r
FreePool (MemorySpaceMap);\r
}\r
+}\r
\r
- mIsFlushingGCD = FALSE;\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
Initialize Interrupt Descriptor Table for interrupt handling.\r
VOID\r
)\r
{\r
- EFI_STATUS Status;\r
- VOID *IdtPtrAlignmentBuffer;\r
- IA32_DESCRIPTOR *IdtPtr;\r
- UINTN Index;\r
- UINTN CurrentHandler;\r
- IA32_DESCRIPTOR Idtr;\r
+ EFI_STATUS Status;\r
+ EFI_VECTOR_HANDOFF_INFO *VectorInfoList;\r
+ EFI_VECTOR_HANDOFF_INFO *VectorInfo;\r
+\r
+ VectorInfo = NULL;\r
+ Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **)&VectorInfoList);\r
+ if ((Status == EFI_SUCCESS) && (VectorInfoList != NULL)) {\r
+ VectorInfo = VectorInfoList;\r
+ }\r
\r
- SetMem (ExternalVectorTable, sizeof(ExternalVectorTable), 0);\r
+ Status = InitializeCpuInterruptHandlers (VectorInfo);\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
\r
- //\r
- // Intialize IDT\r
- //\r
- CurrentHandler = (UINTN)AsmIdtVector00;\r
- for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++, CurrentHandler += 0x08) {\r
- gIdtTable[Index].Bits.OffsetLow = (UINT16)CurrentHandler;\r
- gIdtTable[Index].Bits.Reserved_0 = 0;\r
- gIdtTable[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
- gIdtTable[Index].Bits.OffsetHigh = (UINT16)(CurrentHandler >> 16);\r
-#if defined (MDE_CPU_X64)\r
- gIdtTable[Index].Bits.OffsetUpper = (UINT32)(CurrentHandler >> 32);\r
- gIdtTable[Index].Bits.Reserved_1 = 0;\r
-#endif\r
+/**\r
+ Callback function for idle events.\r
+\r
+ @param Event Event whose notification function is being invoked.\r
+ @param Context The pointer to the notification function's context,\r
+ which is implementation-dependent.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+IdleLoopEventCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ CpuSleep ();\r
+}\r
+\r
+/**\r
+ Ensure the compatibility of a memory space descriptor with the MMIO aperture.\r
+\r
+ The memory space descriptor can come from the GCD memory space map, or it can\r
+ represent a gap between two neighboring memory space descriptors. In the\r
+ latter case, the GcdMemoryType field is expected to be\r
+ EfiGcdMemoryTypeNonExistent.\r
+\r
+ If the memory space descriptor already has type\r
+ EfiGcdMemoryTypeMemoryMappedIo, and its capabilities are a superset of the\r
+ required capabilities, then no action is taken -- it is by definition\r
+ compatible with the aperture.\r
+\r
+ Otherwise, the intersection of the memory space descriptor is calculated with\r
+ the aperture. If the intersection is the empty set (no overlap), no action is\r
+ taken; the memory space descriptor is compatible with the aperture.\r
+\r
+ Otherwise, the type of the descriptor is investigated again. If the type is\r
+ EfiGcdMemoryTypeNonExistent (representing a gap, or a genuine descriptor with\r
+ such a type), then an attempt is made to add the intersection as MMIO space\r
+ to the GCD memory space map, with the specified capabilities. This ensures\r
+ continuity for the aperture, and the descriptor is deemed compatible with the\r
+ aperture.\r
+\r
+ Otherwise, the memory space descriptor is incompatible with the MMIO\r
+ aperture.\r
+\r
+ @param[in] Base Base address of the aperture.\r
+ @param[in] Length Length of the aperture.\r
+ @param[in] Capabilities Capabilities required by the aperture.\r
+ @param[in] Descriptor The descriptor to ensure compatibility with the\r
+ aperture for.\r
+\r
+ @retval EFI_SUCCESS The descriptor is compatible. The GCD memory\r
+ space map may have been updated, for\r
+ continuity within the aperture.\r
+ @retval EFI_INVALID_PARAMETER The descriptor is incompatible.\r
+ @return Error codes from gDS->AddMemorySpace().\r
+**/\r
+EFI_STATUS\r
+IntersectMemoryDescriptor (\r
+ IN UINT64 Base,\r
+ IN UINT64 Length,\r
+ IN UINT64 Capabilities,\r
+ IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor\r
+ )\r
+{\r
+ UINT64 IntersectionBase;\r
+ UINT64 IntersectionEnd;\r
+ EFI_STATUS Status;\r
+\r
+ if ((Descriptor->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&\r
+ ((Descriptor->Capabilities & Capabilities) == Capabilities))\r
+ {\r
+ return EFI_SUCCESS;\r
}\r
\r
- //\r
- // Get original IDT address and size.\r
- //\r
- AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
+ IntersectionBase = MAX (Base, Descriptor->BaseAddress);\r
+ IntersectionEnd = MIN (\r
+ Base + Length,\r
+ Descriptor->BaseAddress + Descriptor->Length\r
+ );\r
+ if (IntersectionBase >= IntersectionEnd) {\r
+ //\r
+ // The descriptor and the aperture don't overlap.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
\r
- //\r
- // Copy original IDT entry.\r
- //\r
- CopyMem (&gIdtTable[0], (VOID *) Idtr.Base, Idtr.Limit + 1);\r
- \r
- //\r
- // Update all IDT enties to use cuurent CS value\r
- //\r
- for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++, CurrentHandler += 0x08) {\r
- gIdtTable[Index].Bits.Selector = AsmReadCs();\r
+ if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
+ Status = gDS->AddMemorySpace (\r
+ EfiGcdMemoryTypeMemoryMappedIo,\r
+ IntersectionBase,\r
+ IntersectionEnd - IntersectionBase,\r
+ Capabilities\r
+ );\r
+\r
+ DEBUG ((\r
+ EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,\r
+ "%a: %a: add [%Lx, %Lx): %r\n",\r
+ gEfiCallerBaseName,\r
+ __FUNCTION__,\r
+ IntersectionBase,\r
+ IntersectionEnd,\r
+ Status\r
+ ));\r
+ return Status;\r
}\r
- \r
- //\r
- // Load IDT Pointer\r
- //\r
- IdtPtrAlignmentBuffer = AllocatePool (sizeof (*IdtPtr) + 16);\r
- IdtPtr = ALIGN_POINTER (IdtPtrAlignmentBuffer, 16);\r
- IdtPtr->Base = (UINT32)(((UINTN)(VOID*) gIdtTable) & (BASE_4GB-1));\r
- IdtPtr->Limit = sizeof (gIdtTable) - 1;\r
\r
- AsmWriteIdtr (IdtPtr);\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "\r
+ "with aperture [%Lx, %Lx) cap %Lx\n",\r
+ gEfiCallerBaseName,\r
+ __FUNCTION__,\r
+ Descriptor->BaseAddress,\r
+ Descriptor->BaseAddress + Descriptor->Length,\r
+ (UINT32)Descriptor->GcdMemoryType,\r
+ Descriptor->Capabilities,\r
+ Base,\r
+ Base + Length,\r
+ Capabilities\r
+ ));\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
\r
- FreePool (IdtPtrAlignmentBuffer);\r
+/**\r
+ Add MMIO space to GCD.\r
+ The routine checks the GCD database and only adds those which are\r
+ not added in the specified range to GCD.\r
\r
- //\r
- // Initialize Exception Handlers\r
- //\r
- for (Index = 0; Index < 32; Index++) {\r
- Status = CpuRegisterInterruptHandler (&gCpu, Index, CommonExceptionHandler);\r
- ASSERT_EFI_ERROR (Status);\r
+ @param Base Base address of the MMIO space.\r
+ @param Length Length of the MMIO space.\r
+ @param Capabilities Capabilities of the MMIO space.\r
+\r
+ @retval EFI_SUCCESS The MMIO space was added successfully.\r
+**/\r
+EFI_STATUS\r
+AddMemoryMappedIoSpace (\r
+ IN UINT64 Base,\r
+ IN UINT64 Length,\r
+ IN UINT64 Capabilities\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN NumberOfDescriptors;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
+\r
+ Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "%a: %a: GetMemorySpaceMap(): %r\n",\r
+ gEfiCallerBaseName,\r
+ __FUNCTION__,\r
+ Status\r
+ ));\r
+ return Status;\r
}\r
\r
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
+ Status = IntersectMemoryDescriptor (\r
+ Base,\r
+ Length,\r
+ Capabilities,\r
+ &MemorySpaceMap[Index]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeMemorySpaceMap;\r
+ }\r
+ }\r
+\r
+ DEBUG_CODE_BEGIN ();\r
//\r
- // Set the pointer to the array of C based exception handling routines.\r
+ // Make sure there are adjacent descriptors covering [Base, Base + Length).\r
+ // It is possible that they have not been merged; merging can be prevented\r
+ // by allocation and different capabilities.\r
//\r
- InitializeExternalVectorTablePtr (ExternalVectorTable);\r
+ UINT64 CheckBase;\r
+ EFI_STATUS CheckStatus;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
+\r
+ for (CheckBase = Base;\r
+ CheckBase < Base + Length;\r
+ CheckBase = Descriptor.BaseAddress + Descriptor.Length)\r
+ {\r
+ CheckStatus = gDS->GetMemorySpaceDescriptor (CheckBase, &Descriptor);\r
+ ASSERT_EFI_ERROR (CheckStatus);\r
+ ASSERT (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo);\r
+ ASSERT ((Descriptor.Capabilities & Capabilities) == Capabilities);\r
+ }\r
+\r
+ DEBUG_CODE_END ();\r
\r
+FreeMemorySpaceMap:\r
+ FreePool (MemorySpaceMap);\r
+\r
+ return Status;\r
}\r
\r
+/**\r
+ Add and allocate CPU local APIC memory mapped space.\r
+\r
+ @param[in]ImageHandle Image handle this driver.\r
+\r
+**/\r
+VOID\r
+AddLocalApicMemorySpace (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS BaseAddress;\r
+\r
+ BaseAddress = (EFI_PHYSICAL_ADDRESS)GetLocalApicBaseAddress ();\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
+ 0,\r
+ SIZE_4KB,\r
+ &BaseAddress,\r
+ ImageHandle,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a: %a: AllocateMemorySpace() Status - %r\n",\r
+ gEfiCallerBaseName,\r
+ __FUNCTION__,\r
+ Status\r
+ ));\r
+ }\r
+}\r
\r
/**\r
Initialize the state information for the CPU Architectural Protocol.\r
EFI_STATUS\r
EFIAPI\r
InitializeCpu (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
EFI_STATUS Status;\r
+ EFI_EVENT IdleLoopEvent;\r
+\r
+ InitializePageTableLib ();\r
+\r
+ InitializeFloatingPointUnits ();\r
\r
//\r
// Make sure interrupts are disabled\r
//\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&mCpuHandle,\r
- &gEfiCpuArchProtocolGuid, &gCpu,\r
+ &gEfiCpuArchProtocolGuid,\r
+ &gCpu,\r
NULL\r
);\r
ASSERT_EFI_ERROR (Status);\r
//\r
RefreshGcdMemoryAttributes ();\r
\r
+ //\r
+ // Add and allocate local APIC memory mapped space\r
+ //\r
+ AddLocalApicMemorySpace (ImageHandle);\r
+\r
+ //\r
+ // Setup a callback for idle events\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ IdleLoopEventCallback,\r
+ NULL,\r
+ &gIdleLoopEventGuid,\r
+ &IdleLoopEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ InitializeMpSupport ();\r
+\r
return Status;\r
}\r
-\r