/** Returns a boolean to indicate whether SEV is enabled @retval TRUE SEV is enabled @retval FALSE SEV is not enabled **/ STATIC BOOLEAN EFIAPI InternalMemEncryptSevIsEnabled ( VOID ) { UINT32 RegEax; MSR_SEV_STATUS_REGISTER Msr; CPUID_MEMORY_ENCRYPTION_INFO_EAX Eax; // // Check if memory encryption leaf exist // AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); if (RegEax >= CPUID_MEMORY_ENCRYPTION_INFO) { // // CPUID Fn8000_001F[EAX] Bit 1 (Sev supported) // AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax.Uint32, NULL, NULL, NULL); if (Eax.Bits.SevBit) { // // Check MSR_0xC0010131 Bit 0 (Sev Enabled) // Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS); if (Msr.Bits.SevBit) { return TRUE; } } } return FALSE; }
/** Display CPUID_SERIAL_NUMBER leaf if it is supported. **/ VOID CpuidSerialNumber ( VOID ) { CPUID_VERSION_INFO_EDX VersionInfoEdx; UINT32 Ecx; UINT32 Edx; Print (L"CPUID_SERIAL_NUMBER (Leaf %08x)\n", CPUID_SERIAL_NUMBER); if (CPUID_SERIAL_NUMBER > gMaximumBasicFunction) { return; } AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32); if (VersionInfoEdx.Bits.PSN == 0) { Print (L" Not Supported\n"); return; } AsmCpuid (CPUID_SERIAL_NUMBER, NULL, NULL, &Ecx, &Edx); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", 0, 0, Ecx, Edx); Print (L" Processor Serial Number = %08x%08x%08x\n", 0, Edx, Ecx); }
/** Calculate the maximum support address. @return the maximum support address. **/ UINT8 CalculateMaximumSupportAddress ( VOID ) { UINT32 RegEax; UINT8 PhysicalAddressBits; VOID *Hob; // // Get physical address bits supported. // Hob = GetFirstHob (EFI_HOB_TYPE_CPU); if (Hob != NULL) { PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; } else { AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x80000008) { AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); PhysicalAddressBits = (UINT8) RegEax; } else { PhysicalAddressBits = 36; } } // // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses. // ASSERT (PhysicalAddressBits <= 52); if (PhysicalAddressBits > 48) { PhysicalAddressBits = 48; } return PhysicalAddressBits; }
/** This function initialize basic context for FRM. **/ VOID InitBasicContext ( VOID ) { UINT32 RegEax; mHostContextCommon.CpuNum = GetCpuNumFromAcpi (); GetPciExpressInfoFromAcpi (&mHostContextCommon.PciExpressBaseAddress, &mHostContextCommon.PciExpressLength); PcdSet64 (PcdPciExpressBaseAddress, mHostContextCommon.PciExpressBaseAddress); if (mHostContextCommon.PciExpressBaseAddress == 0) { CpuDeadLoop (); } mHostContextCommon.AcpiTimerIoPortBaseAddress = GetAcpiTimerPort (&mHostContextCommon.AcpiTimerWidth); PcdSet16 (PcdAcpiTimerIoPortBaseAddress, mHostContextCommon.AcpiTimerIoPortBaseAddress); PcdSet8 (PcdAcpiTimerWidth, mHostContextCommon.AcpiTimerWidth); if (mHostContextCommon.AcpiTimerIoPortBaseAddress == 0) { CpuDeadLoop (); } mHostContextCommon.ResetIoPortBaseAddress = GetAcpiResetPort (); mHostContextCommon.AcpiPmControlIoPortBaseAddress = GetAcpiPmControlPort (); if (mHostContextCommon.AcpiPmControlIoPortBaseAddress == 0) { CpuDeadLoop (); } mHostContextCommon.HostContextPerCpu = AllocatePages (FRM_SIZE_TO_PAGES(sizeof(FRM_HOST_CONTEXT_PER_CPU)) * mHostContextCommon.CpuNum); mGuestContextCommon.GuestContextPerCpu = AllocatePages (FRM_SIZE_TO_PAGES(sizeof(FRM_GUEST_CONTEXT_PER_CPU)) * mHostContextCommon.CpuNum); mHostContextCommon.LowMemoryBase = mCommunicationData.LowMemoryBase; mHostContextCommon.LowMemorySize = mCommunicationData.LowMemorySize; mHostContextCommon.LowMemoryBackupBase = (UINT64)(UINTN)AllocatePages (FRM_SIZE_TO_PAGES ((UINTN)mCommunicationData.LowMemorySize)); // // Save current context // mBspIndex = ApicToIndex (ReadLocalApicId ()); mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr0 = AsmReadCr0 (); mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr3 = AsmReadCr3 (); mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr4 = AsmReadCr4 (); AsmReadGdtr (&mGuestContextCommon.GuestContextPerCpu[mBspIndex].Gdtr); AsmReadIdtr (&mGuestContextCommon.GuestContextPerCpu[mBspIndex].Idtr); AsmCpuid (CPUID_EXTENDED_INFORMATION, &RegEax, NULL, NULL, NULL); if (RegEax >= CPUID_EXTENDED_ADDRESS_SIZE) { AsmCpuid (CPUID_EXTENDED_ADDRESS_SIZE, &RegEax, NULL, NULL, NULL); mHostContextCommon.PhysicalAddressBits = (UINT8)RegEax; } else { mHostContextCommon.PhysicalAddressBits = 36; } }
/** Display CPUID_BRAND_STRING1, CPUID_BRAND_STRING2 and CPUID_BRAND_STRING3 leafs. Also display these three leafs as a single brand string. **/ VOID CpuidProcessorBrandString ( VOID ) { CPUID_BRAND_STRING_DATA Eax; CPUID_BRAND_STRING_DATA Ebx; CPUID_BRAND_STRING_DATA Ecx; CPUID_BRAND_STRING_DATA Edx; // // Array to store brand string from 3 brand string leafs with // 4 32-bit brand string values per leaf and an extra value to // null terminate the string. // UINT32 BrandString[3 * 4 + 1]; if (CPUID_BRAND_STRING1 <= gMaximumExtendedFunction) { AsmCpuid (CPUID_BRAND_STRING1, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32); Print (L"CPUID_BRAND_STRING1 (Leaf %08x)\n", CPUID_BRAND_STRING1); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32); BrandString[0] = Eax.Uint32; BrandString[1] = Ebx.Uint32; BrandString[2] = Ecx.Uint32; BrandString[3] = Edx.Uint32; } if (CPUID_BRAND_STRING2 <= gMaximumExtendedFunction) { AsmCpuid (CPUID_BRAND_STRING2, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32); Print (L"CPUID_BRAND_STRING2 (Leaf %08x)\n", CPUID_BRAND_STRING2); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32); BrandString[4] = Eax.Uint32; BrandString[5] = Ebx.Uint32; BrandString[6] = Ecx.Uint32; BrandString[7] = Edx.Uint32; } if (CPUID_BRAND_STRING3 <= gMaximumExtendedFunction) { AsmCpuid (CPUID_BRAND_STRING3, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32); Print (L"CPUID_BRAND_STRING3 (Leaf %08x)\n", CPUID_BRAND_STRING3); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32); BrandString[8] = Eax.Uint32; BrandString[9] = Ebx.Uint32; BrandString[10] = Ecx.Uint32; BrandString[11] = Edx.Uint32; } BrandString[12] = 0; Print (L"Brand String = %a\n", (CHAR8 *)BrandString); }
/** Check if XD feature is supported by a processor. **/ VOID CheckFeatureSupported ( VOID ) { UINT32 RegEax; UINT32 RegEdx; MSR_IA32_MISC_ENABLE_REGISTER MiscEnableMsr; if (mXdSupported) { AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); if (RegEax <= CPUID_EXTENDED_FUNCTION) { // // Extended CPUID functions are not supported on this processor. // mXdSupported = FALSE; } AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx); if ((RegEdx & CPUID1_EDX_XD_SUPPORT) == 0) { // // Execute Disable Bit feature is not supported on this processor. // mXdSupported = FALSE; } } if (mBtsSupported) { AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx); if ((RegEdx & CPUID1_EDX_BTS_AVAILABLE) != 0) { // // Per IA32 manuals: // When CPUID.1:EDX[21] is set, the following BTS facilities are available: // 1. The BTS_UNAVAILABLE flag in the IA32_MISC_ENABLE MSR indicates the // availability of the BTS facilities, including the ability to set the BTS and // BTINT bits in the MSR_DEBUGCTLA MSR. // 2. The IA32_DS_AREA MSR can be programmed to point to the DS save area. // MiscEnableMsr.Uint64 = AsmReadMsr64 (MSR_IA32_MISC_ENABLE); if (MiscEnableMsr.Bits.BTS == 1) { // // BTS facilities is not supported if MSR_IA32_MISC_ENABLE.BTS bit is set. // mBtsSupported = FALSE; } } } }
/** Display CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING leaf. **/ VOID CpuidArchitecturalPerformanceMonitoring ( VOID ) { CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING_EAX Eax; CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING_EBX Ebx; CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING_EDX Edx; if (CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING > gMaximumBasicFunction) { return; } AsmCpuid (CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING, &Eax.Uint32, &Ebx.Uint32, NULL, &Edx.Uint32); Print (L"CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING (Leaf %08x)\n", CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, 0, Edx.Uint32); PRINT_BIT_FIELD (Eax, ArchPerfMonVerID); PRINT_BIT_FIELD (Eax, PerformanceMonitorCounters); PRINT_BIT_FIELD (Eax, PerformanceMonitorCounterWidth); PRINT_BIT_FIELD (Eax, EbxBitVectorLength); PRINT_BIT_FIELD (Ebx, UnhaltedCoreCycles); PRINT_BIT_FIELD (Ebx, InstructionsRetired); PRINT_BIT_FIELD (Ebx, UnhaltedReferenceCycles); PRINT_BIT_FIELD (Ebx, LastLevelCacheReferences); PRINT_BIT_FIELD (Ebx, LastLevelCacheMisses); PRINT_BIT_FIELD (Ebx, BranchInstructionsRetired); PRINT_BIT_FIELD (Ebx, AllBranchMispredictRetired); PRINT_BIT_FIELD (Edx, FixedFunctionPerformanceCounters); PRINT_BIT_FIELD (Edx, FixedFunctionPerformanceCounterWidth); }
/** Save the volatile registers required to be restored following INIT IPI. @param VolatileRegisters Returns buffer saved the volatile resisters **/ VOID SaveVolatileRegisters ( OUT CPU_VOLATILE_REGISTERS *VolatileRegisters ) { UINT32 RegEdx; VolatileRegisters->Cr0 = AsmReadCr0 (); VolatileRegisters->Cr3 = AsmReadCr3 (); VolatileRegisters->Cr4 = AsmReadCr4 (); AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx); if ((RegEdx & BIT2) != 0) { // // If processor supports Debugging Extensions feature // by CPUID.[EAX=01H]:EDX.BIT2 // VolatileRegisters->Dr0 = AsmReadDr0 (); VolatileRegisters->Dr1 = AsmReadDr1 (); VolatileRegisters->Dr2 = AsmReadDr2 (); VolatileRegisters->Dr3 = AsmReadDr3 (); VolatileRegisters->Dr6 = AsmReadDr6 (); VolatileRegisters->Dr7 = AsmReadDr7 (); } }
/** This function will return current CPU_SMM_CLASS accroding to CPUID mapping. @return The point to current CPU_SMM_CLASS **/ CPU_SMM_CLASS * GetCpuFamily ( VOID ) { UINT32 ClassIndex; UINT32 Index; UINT32 Count; CPUID_MAPPING *CpuMapping; UINT32 RegEax; AsmCpuid (EFI_CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL); for (ClassIndex = 0; ClassIndex < sizeof(mCpuClasstable)/sizeof(mCpuClasstable[0]); ClassIndex++) { CpuMapping = mCpuClasstable[ClassIndex]->MappingTable; Count = mCpuClasstable[ClassIndex]->MappingCount; for (Index = 0; Index < Count; Index++) { if ((CpuMapping[Index].Signature & CpuMapping[Index].Mask) == (RegEax & CpuMapping[Index].Mask)) { return mCpuClasstable[ClassIndex]; } } } // Not found!!! Should not happen ASSERT (FALSE); return NULL; }
/** Display CPUID_MONITOR_MWAIT leaf. **/ VOID CpuidMonitorMwait ( VOID ) { CPUID_MONITOR_MWAIT_EAX Eax; CPUID_MONITOR_MWAIT_EBX Ebx; CPUID_MONITOR_MWAIT_ECX Ecx; CPUID_MONITOR_MWAIT_EDX Edx; if (CPUID_MONITOR_MWAIT > gMaximumBasicFunction) { return; } AsmCpuid (CPUID_MONITOR_MWAIT, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32); Print (L"CPUID_MONITOR_MWAIT (Leaf %08x)\n", CPUID_MONITOR_MWAIT); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32); PRINT_BIT_FIELD (Eax, SmallestMonitorLineSize); PRINT_BIT_FIELD (Ebx, LargestMonitorLineSize); PRINT_BIT_FIELD (Ecx, ExtensionsSupported); PRINT_BIT_FIELD (Ecx, InterruptAsBreak); PRINT_BIT_FIELD (Edx, C0States); PRINT_BIT_FIELD (Edx, C1States); PRINT_BIT_FIELD (Edx, C2States); PRINT_BIT_FIELD (Edx, C3States); PRINT_BIT_FIELD (Edx, C4States); PRINT_BIT_FIELD (Edx, C5States); PRINT_BIT_FIELD (Edx, C6States); PRINT_BIT_FIELD (Edx, C7States); }
/** Display CPUID_SIGNATURE leaf. **/ VOID CpuidSignature ( VOID ) { UINT32 Eax; UINT32 Ebx; UINT32 Ecx; UINT32 Edx; CHAR8 Signature[13]; if (CPUID_SIGNATURE > gMaximumBasicFunction) { return; } AsmCpuid (CPUID_SIGNATURE, &Eax, &Ebx, &Ecx, &Edx); Print (L"CPUID_SIGNATURE (Leaf %08x)\n", CPUID_SIGNATURE); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, Ebx, Ecx, Edx); PRINT_VALUE (Eax, MaximumLeaf); *(UINT32 *)(Signature + 0) = Ebx; *(UINT32 *)(Signature + 4) = Edx; *(UINT32 *)(Signature + 8) = Ecx; Signature [12] = 0; Print (L" Signature = %a\n", Signature); gMaximumBasicFunction = Eax; }
/** Restore the volatile registers following INIT IPI. @param VolatileRegisters Pointer to volatile resisters @param IsRestoreDr TRUE: Restore DRx if supported FALSE: Do not restore DRx **/ VOID RestoreVolatileRegisters ( IN CPU_VOLATILE_REGISTERS *VolatileRegisters, IN BOOLEAN IsRestoreDr ) { UINT32 RegEdx; AsmWriteCr0 (VolatileRegisters->Cr0); AsmWriteCr3 (VolatileRegisters->Cr3); AsmWriteCr4 (VolatileRegisters->Cr4); if (IsRestoreDr) { AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx); if ((RegEdx & BIT2) != 0) { // // If processor supports Debugging Extensions feature // by CPUID.[EAX=01H]:EDX.BIT2 // AsmWriteDr0 (VolatileRegisters->Dr0); AsmWriteDr1 (VolatileRegisters->Dr1); AsmWriteDr2 (VolatileRegisters->Dr2); AsmWriteDr3 (VolatileRegisters->Dr3); AsmWriteDr6 (VolatileRegisters->Dr6); AsmWriteDr7 (VolatileRegisters->Dr7); } } }
/** Display CPUID_EXTENDED_CPU_SIG leaf. **/ VOID CpuidExtendedCpuSig ( VOID ) { UINT32 Eax; CPUID_EXTENDED_CPU_SIG_ECX Ecx; CPUID_EXTENDED_CPU_SIG_EDX Edx; if (CPUID_EXTENDED_CPU_SIG > gMaximumExtendedFunction) { return; } AsmCpuid (CPUID_EXTENDED_CPU_SIG, &Eax, NULL, &Ecx.Uint32, &Edx.Uint32); Print (L"CPUID_EXTENDED_CPU_SIG (Leaf %08x)\n", CPUID_EXTENDED_CPU_SIG); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, 0, Ecx.Uint32, Edx.Uint32); PRINT_BIT_FIELD (Ecx, LAHF_SAHF); PRINT_BIT_FIELD (Ecx, LZCNT); PRINT_BIT_FIELD (Ecx, PREFETCHW); PRINT_BIT_FIELD (Edx, SYSCALL_SYSRET); PRINT_BIT_FIELD (Edx, NX); PRINT_BIT_FIELD (Edx, Page1GB); PRINT_BIT_FIELD (Edx, RDTSCP); PRINT_BIT_FIELD (Edx, LM); }
/** Display CPUID_THERMAL_POWER_MANAGEMENT leaf. **/ VOID CpuidThermalPowerManagement ( VOID ) { CPUID_THERMAL_POWER_MANAGEMENT_EAX Eax; CPUID_THERMAL_POWER_MANAGEMENT_EBX Ebx; CPUID_THERMAL_POWER_MANAGEMENT_ECX Ecx; if (CPUID_THERMAL_POWER_MANAGEMENT > gMaximumBasicFunction) { return; } AsmCpuid (CPUID_THERMAL_POWER_MANAGEMENT, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, NULL); Print (L"CPUID_THERMAL_POWER_MANAGEMENT (Leaf %08x)\n", CPUID_THERMAL_POWER_MANAGEMENT); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, 0); PRINT_BIT_FIELD (Eax, DigitalTemperatureSensor); PRINT_BIT_FIELD (Eax, TurboBoostTechnology); PRINT_BIT_FIELD (Eax, ARAT); PRINT_BIT_FIELD (Eax, PLN); PRINT_BIT_FIELD (Eax, ECMD); PRINT_BIT_FIELD (Eax, PTM); PRINT_BIT_FIELD (Eax, HWP); PRINT_BIT_FIELD (Eax, HWP_Notification); PRINT_BIT_FIELD (Eax, HWP_Activity_Window); PRINT_BIT_FIELD (Eax, HWP_Energy_Performance_Preference); PRINT_BIT_FIELD (Eax, HWP_Package_Level_Request); PRINT_BIT_FIELD (Eax, HDC); PRINT_BIT_FIELD (Ebx, InterruptThresholds); PRINT_BIT_FIELD (Ecx, HardwareCoordinationFeedback); PRINT_BIT_FIELD (Ecx, PerformanceEnergyBias); }
/** Check if 1-GByte pages is supported by processor or not. @retval TRUE 1-GByte pages is supported. @retval FALSE 1-GByte pages is not supported. **/ BOOLEAN Is1GPageSupport ( VOID ) { UINT32 RegEax; UINT32 RegEdx; AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x80000001) { AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); if ((RegEdx & BIT26) != 0) { return TRUE; } } return FALSE; }
VOID PrepareHobCpu ( VOID ) { UINT32 CpuidEax; // // Create a CPU hand-off information // gHob->Cpu.SizeOfMemorySpace = 36; AsmCpuid (EFI_CPUID_EXTENDED_FUNCTION, &CpuidEax, NULL, NULL, NULL); if (CpuidEax >= CPUID_EXTENDED_ADD_SIZE) { AsmCpuid (CPUID_EXTENDED_ADD_SIZE, &CpuidEax, NULL, NULL, NULL); gHob->Cpu.SizeOfMemorySpace = (UINT8)(CpuidEax & 0xFF); } }
/** The function will check if IA32 PAE is supported. @retval TRUE IA32 PAE is supported. @retval FALSE IA32 PAE is not supported. **/ BOOLEAN IsIa32PaeSupport ( VOID ) { UINT32 RegEax; UINT32 RegEdx; BOOLEAN Ia32PaeSupport; Ia32PaeSupport = FALSE; AsmCpuid (0x0, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x1) { AsmCpuid (0x1, NULL, NULL, NULL, &RegEdx); if ((RegEdx & BIT6) != 0) { Ia32PaeSupport = TRUE; } } return Ia32PaeSupport; }
/** Get the initial local APIC ID of the executing processor assigned by hardware upon power on or reset. In xAPIC mode, the initial local APIC ID is 8-bit, and may be different from current APIC ID. In x2APIC mode, the local APIC ID can't be changed and there is no concept of initial APIC ID. In this case, the 32-bit local APIC ID is returned as initial APIC ID. @return 32-bit initial local APIC ID of the executing processor. **/ UINT32 EFIAPI GetInitialApicId ( VOID ) { UINT32 RegEbx; if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) { AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL); return RegEbx >> 24; } else {
/** Get microcode update signature of currently loaded microcode update. @return Microcode signature. **/ UINT32 GetCurrentMicrocodeSignature ( VOID ) { UINT64 Signature; AsmWriteMsr64 (EFI_MSR_IA32_BIOS_SIGN_ID, 0); AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL); Signature = AsmReadMsr64 (EFI_MSR_IA32_BIOS_SIGN_ID); return (UINT32) RShiftU64 (Signature, 32); }
/** Determines whether or not RDRAND instruction is supported by the host hardware. @retval EFI_SUCCESS RDRAND instruction supported. @retval EFI_UNSUPPORTED RDRAND instruction not supported. **/ EFI_STATUS EFIAPI IsRdRandSupported ( VOID ) { EFI_STATUS Status; UINT32 RegEax; UINT32 RegEbx; UINT32 RegEcx; UINT32 RegEdx; BOOLEAN IsIntelCpu; Status = EFI_UNSUPPORTED; IsIntelCpu = FALSE; // // Checks whether the current processor is an Intel product by CPUID. // AsmCpuid (0, &RegEax, &RegEbx, &RegEcx, &RegEdx); if ((CompareMem ((CHAR8 *)(&RegEbx), "Genu", 4) == 0) && (CompareMem ((CHAR8 *)(&RegEdx), "ineI", 4) == 0) && (CompareMem ((CHAR8 *)(&RegEcx), "ntel", 4) == 0)) { IsIntelCpu = TRUE; } if (IsIntelCpu) { // // Determine RDRAND support by examining bit 30 of the ECX register returned by CPUID. // A value of 1 indicates that processor supports RDRAND instruction. // AsmCpuid (1, 0, 0, &RegEcx, 0); if ((RegEcx & RDRAND_MASK) == RDRAND_MASK) { Status = EFI_SUCCESS; } } return Status; }
/** Get AP loop mode. @param MonitorFilterSize Returns the largest monitor-line size in bytes. @return The AP loop mode. **/ UINT8 GetApLoopMode ( OUT UINT16 *MonitorFilterSize ) { UINT8 ApLoopMode; UINT32 RegEbx; UINT32 RegEcx; UINT32 RegEdx; ASSERT (MonitorFilterSize != NULL); ApLoopMode = PcdGet8 (PcdCpuApLoopMode); ASSERT (ApLoopMode >= ApInHltLoop && ApLoopMode <= ApInRunLoop); if (ApLoopMode == ApInMwaitLoop) { AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &RegEcx, NULL); if ((RegEcx & BIT3) == 0) { // // If processor does not support MONITOR/MWAIT feature // by CPUID.[EAX=01H]:ECX.BIT3, force AP in Hlt-loop mode // ApLoopMode = ApInHltLoop; } } if (ApLoopMode == ApInHltLoop) { *MonitorFilterSize = 0; } else if (ApLoopMode == ApInRunLoop) { *MonitorFilterSize = sizeof (UINT32); } else if (ApLoopMode == ApInMwaitLoop) { // // CPUID.[EAX=05H]:EBX.BIT0-15: Largest monitor-line size in bytes // CPUID.[EAX=05H].EDX: C-states supported using MWAIT // AsmCpuid (CPUID_MONITOR_MWAIT, NULL, &RegEbx, NULL, &RegEdx); *MonitorFilterSize = RegEbx & 0xFFFF; } return ApLoopMode; }
UINT64 InitializeAddressMtrrMask ( VOID ) { UINT32 RegEax; UINT8 PhysicalAddressBits; UINT64 ValidMtrrBitsMask; AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x80000008) { AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); PhysicalAddressBits = (UINT8) RegEax; } else { PhysicalAddressBits = 36; } ValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1; return (ValidMtrrBitsMask & 0xfffffffffffff000ULL); }
/** Calculate and save the maximum support address. **/ VOID SmmMemLibInternalCalculateMaximumSupportAddress ( VOID ) { VOID *Hob; UINT32 RegEax; UINT8 PhysicalAddressBits; // // Get physical address bits supported. // Hob = GetFirstHob (EFI_HOB_TYPE_CPU); if (Hob != NULL) { PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; } else { AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x80000008) { AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); PhysicalAddressBits = (UINT8) RegEax; } else { PhysicalAddressBits = 36; } } // // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses. // ASSERT (PhysicalAddressBits <= 52); if (PhysicalAddressBits > 48) { PhysicalAddressBits = 48; } // // Save the maximum support address in one global variable // mSmmMemLibInternalMaximumSupportAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, PhysicalAddressBits) - 1); DEBUG ((EFI_D_INFO, "mSmmMemLibInternalMaximumSupportAddress = 0x%lx\n", mSmmMemLibInternalMaximumSupportAddress)); }
/** Initializes the valid bits mask and valid address mask for MTRRs. This function initializes the valid bits mask and valid address mask for MTRRs. @param MtrrValidBitsMask The mask for the valid bit of the MTRR @param MtrrValidAddressMask The valid address mask for the MTRR **/ VOID MtrrLibInitializeMtrrMask ( OUT UINT64 *MtrrValidBitsMask, OUT UINT64 *MtrrValidAddressMask ) { UINT32 RegEax; UINT8 PhysicalAddressBits; AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x80000008) { AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); PhysicalAddressBits = (UINT8) RegEax; *MtrrValidBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1; *MtrrValidAddressMask = *MtrrValidBitsMask & 0xfffffffffffff000ULL; } else { *MtrrValidBitsMask = MTRR_LIB_CACHE_VALID_ADDRESS; *MtrrValidAddressMask = 0xFFFFFFFF; } }
/** Display CPUID_EXTENDED_FUNCTION leaf. **/ VOID CpuidExtendedFunction ( VOID ) { UINT32 Eax; AsmCpuid (CPUID_EXTENDED_FUNCTION, &Eax, NULL, NULL, NULL); Print (L"CPUID_EXTENDED_FUNCTION (Leaf %08x)\n", CPUID_EXTENDED_FUNCTION); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, 0, 0, 0); PRINT_VALUE (Eax, MaximumExtendedFunction); gMaximumExtendedFunction = Eax; }
/** Initialize IDT entries to support source level debug. **/ VOID InitializeDebugIdt ( VOID ) { IA32_IDT_GATE_DESCRIPTOR *IdtEntry; UINTN InterruptHandler; IA32_DESCRIPTOR IdtDescriptor; UINTN Index; UINT16 CodeSegment; UINT32 RegEdx; AsmReadIdtr (&IdtDescriptor); // // Use current CS as the segment selector of interrupt gate in IDT // CodeSegment = AsmReadCs (); IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base; for (Index = 0; Index < 20; Index ++) { if (((PcdGet32 (PcdExceptionsIgnoredByDebugger) & ~(BIT1 | BIT3)) & (1 << Index)) != 0) { // // If the exception is masked to be reserved except for INT1 and INT3, skip it // continue; } InterruptHandler = (UINTN)&Exception0Handle + Index * ExceptionStubHeaderSize; IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler; IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16); IdtEntry[Index].Bits.Selector = CodeSegment; IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; } InterruptHandler = (UINTN) &TimerInterruptHandle; IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler; IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16); IdtEntry[DEBUG_TIMER_VECTOR].Bits.Selector = CodeSegment; IdtEntry[DEBUG_TIMER_VECTOR].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; // // If the CPU supports Debug Extensions(CPUID:01 EDX:BIT2), then // Set DE flag in CR4 to enable IO breakpoint // AsmCpuid (1, NULL, NULL, NULL, &RegEdx); if ((RegEdx & BIT2) != 0) { AsmWriteCr4 (AsmReadCr4 () | BIT3); } }
/** Display CPUID_DIRECT_CACHE_ACCESS_INFO leaf. **/ VOID CpuidDirectCacheAccessInfo ( VOID ) { UINT32 Eax; if (CPUID_DIRECT_CACHE_ACCESS_INFO > gMaximumBasicFunction) { return; } AsmCpuid (CPUID_DIRECT_CACHE_ACCESS_INFO, &Eax, NULL, NULL, NULL); Print (L"CPUID_DIRECT_CACHE_ACCESS_INFO (Leaf %08x)\n", CPUID_DIRECT_CACHE_ACCESS_INFO); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, 0, 0, 0); }
/** Display CPUID_EXTENDED_TIME_STAMP_COUNTER leaf. **/ VOID CpuidExtendedTimeStampCounter ( VOID ) { CPUID_EXTENDED_TIME_STAMP_COUNTER_EDX Edx; if (CPUID_EXTENDED_TIME_STAMP_COUNTER > gMaximumExtendedFunction) { return; } AsmCpuid (CPUID_EXTENDED_TIME_STAMP_COUNTER, NULL, NULL, NULL, &Edx.Uint32); Print (L"CPUID_EXTENDED_TIME_STAMP_COUNTER (Leaf %08x)\n", CPUID_EXTENDED_TIME_STAMP_COUNTER); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", 0, 0, 0, Edx.Uint32); PRINT_BIT_FIELD (Edx, InvariantTsc); }
/** Display CPUID_TIME_STAMP_COUNTER leaf. **/ VOID CpuidTimeStampCounter ( VOID ) { UINT32 Eax; UINT32 Ebx; if (CPUID_TIME_STAMP_COUNTER > gMaximumBasicFunction) { return; } AsmCpuid (CPUID_TIME_STAMP_COUNTER, &Eax, &Ebx, NULL, NULL); Print (L"CPUID_TIME_STAMP_COUNTER (Leaf %08x)\n", CPUID_TIME_STAMP_COUNTER); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, Ebx, 0, 0); }
/** Display CPUID_VIR_PHY_ADDRESS_SIZE leaf. **/ VOID CpuidVirPhyAddressSize ( VOID ) { CPUID_VIR_PHY_ADDRESS_SIZE_EAX Eax; if (CPUID_VIR_PHY_ADDRESS_SIZE > gMaximumExtendedFunction) { return; } AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &Eax.Uint32, NULL, NULL, NULL); Print (L"CPUID_VIR_PHY_ADDRESS_SIZE (Leaf %08x)\n", CPUID_VIR_PHY_ADDRESS_SIZE); Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, 0, 0, 0); PRINT_BIT_FIELD (Eax, PhysicalAddressBits); PRINT_BIT_FIELD (Eax, LinearAddressBits); }