24#include <Protocol/PciIo.h>
25#include <Pi/PiBootMode.h>
27#include <Library/BaseLib.h>
28#include <Library/BaseMemoryLib.h>
29#include <Library/BaseOverflowLib.h>
30#include <Library/DebugLib.h>
31#include <Library/HobLib.h>
32#include <Library/IoLib.h>
33#include <Library/MemoryAllocationLib.h>
35#include <Library/PciLib.h>
38#include <Library/UefiBootServicesTableLib.h>
39#include <Library/UefiRuntimeServicesTableLib.h>
41#include <Register/Msr.h>
47 OUT CONST CHAR8 **Type OPTIONAL
52 EFI_HOB_GUID_TYPE *HobAcpiDescription;
85 *Type =
"Braswell PMC";
103 }
else if (Type != NULL) {
104 *Type =
"Invalid INTEL PMC";
106 }
else if (Type != NULL) {
110 *Type =
"Unknown INTEL";
120 *Type =
"PMC PIIX4 ACPI";
128 if (TimerAddr == 0) {
133 AsmCpuid (CPUID_SIGNATURE, NULL, &CpuVendor, NULL, NULL);
139 if (TimerAddr == MAX_UINT32) {
152 if (TimerAddr == 0) {
157 if (HobAcpiDescription != NULL) {
161 TimerAddr = (UINTN)AcpiDescription->
PM_TMR_BLK.Address;
174 IN BOOLEAN Recalculate
182 STATIC UINT64 TSCFrequency = 0;
186 UINT64 TscTicksDelta;
189 UINT32 AcpiTicksDelta;
190 UINT32 AcpiTicksDuration;
191 BOOLEAN HasInterrupts;
199 return EFI_UNSUPPORTED;
205 if (TSCFrequency == 0) {
206 VariableSize =
sizeof (TSCFrequency);
207 Status =
gRT->GetVariable (
215 Status = EFI_ALREADY_STARTED;
222 if (TSCFrequency == 0) {
225 if (TimerAddr != 0) {
233 if (AcpiTick0 != AcpiTick1) {
247 PrevTpl =
gBS->RaiseTPL (TPL_HIGH_LEVEL);
248 HasInterrupts = SaveAndDisableInterrupts ();
249 AsmMeasureTicks (AcpiTicksDuration, TimerAddr, &AcpiTicksDelta, &TscTicksDelta);
254 gBS->RestoreTPL (PrevTpl);
263 DEBUG ((DEBUG_VERBOSE,
"TscFrequency %lld\n", TSCFrequency));
268 if ((TSCFrequency != 0) && (Status == EFI_NOT_FOUND)) {
276 EFI_VARIABLE_BOOTSERVICE_ACCESS,
277 sizeof (TSCFrequency),
289 IN UINT64 *FsbFrequency,
290 IN UINT32 FsbFrequncyCount
295 if (FsbFrequncyCount < 5) {
306 "OCCPU: Selecting FSB freq by PLL freq %u from %Lu %Lu %Lu %Lu %Lu\n",
318 return FsbFrequency[0];
321 if ((Pll >= 1063) && (Pll <= 1069)) {
322 return FsbFrequency[0];
325 if ((Pll >= 530) && (Pll <= 536)) {
326 return FsbFrequency[1];
329 if ((Pll >= 797) && (Pll <= 803)) {
330 return FsbFrequency[2];
333 if ((Pll >= 663) && (Pll <= 669)) {
334 return FsbFrequency[3];
337 if ((Pll >= 1330) && (Pll <= 1336)) {
338 return FsbFrequency[4];
346 OUT UINT64 *FSBFrequency OPTIONAL,
347 IN BOOLEAN Recalculate
353 STATIC BOOLEAN ObtainedFreqs = FALSE;
354 STATIC UINT64 FsbFreq = 0;
355 STATIC UINT64 TscFreq = 0;
367 ObtainedFreqs = FALSE;
372 if (!ObtainedFreqs) {
373 ObtainedFreqs = TRUE;
374 Size =
sizeof (FsbFreq);
376 Status =
gBS->LocateProtocol (
379 (VOID **)&PlatformInfo
381 if (!EFI_ERROR (Status)) {
389 if (EFI_ERROR (Status)) {
390 DEBUG ((DEBUG_INFO,
"OCCPU: Failed to get FSBFrequency first data - %r, trying HOB method\n", Status));
400 if (EFI_ERROR (Status)) {
401 DEBUG ((DEBUG_INFO,
"OCCPU: Failed to get FSBFrequency data using HOB method - %r, trying legacy\n", Status));
408 if (!EFI_ERROR (Status)) {
409 if ((
Size >=
sizeof (UINT64)) && (
Size %
sizeof (UINT64) == 0)) {
412 DEBUG ((DEBUG_INFO,
"OCCPU: Invalid FSBFrequency list size %u - %r\n",
Size, Status));
413 Status = EFI_INVALID_PARAMETER;
420 DEBUG ((DEBUG_VERBOSE,
"OCCPU: Failed to locate ApplePlatformInfo protocol - %r\n", Status));
427 if (EFI_ERROR (Status)) {
428 DEBUG ((DEBUG_INFO,
"OCCPU: Failed to get FSBFrequency data using Apple Platform Info - %r\n", Status));
439 "OCCPU: Found nForce MCP MC 0x%08X (UN44 0x%08X, UN78 0x%08X, DVD 0x%016Lx, DIV 0x%08X)\n",
450 Status = EFI_SUCCESS;
456 if (EFI_ERROR (Status)) {
466 if (FSBFrequency != NULL) {
467 *FSBFrequency = FsbFreq;
475 OUT UINT64 *CPUFrequency,
476 OUT UINT64 *TscAdjustPtr OPTIONAL,
477 IN BOOLEAN Recalculate
485 STATIC BOOLEAN ObtainedARTFreq = FALSE;
486 STATIC UINT64 ARTFrequency = 0;
487 STATIC UINT64 CPUFrequencyFromART = 0;
492 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_EBX CpuidFeatureFlagsEbx;
493 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX CpuidFeatureFlagsEcx;
494 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_EDX CpuidFeatureFlagsEdx;
495 UINT32 CpuidDenominatorEax;
496 UINT32 CpuidNumeratorEbx;
497 UINT32 CpuidARTFrequencyEcx;
498 CPUID_PROCESSOR_FREQUENCY_EAX CpuidFrequencyEax;
500 UINT64 CPUFrequencyFromTSC;
501 CPUID_VERSION_INFO_EAX CpuidVerEax;
505 ObtainedARTFreq = FALSE;
507 CPUFrequencyFromART = 0;
510 if (!ObtainedARTFreq) {
511 ObtainedARTFreq = TRUE;
516 AsmCpuid (CPUID_SIGNATURE, &MaxId, &CpuVendor, NULL, NULL);
521 if (MaxId >= CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) {
523 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
526 &CpuidFeatureFlagsEbx.Uint32,
527 &CpuidFeatureFlagsEcx.Uint32,
528 &CpuidFeatureFlagsEdx.Uint32
530 if (CpuidFeatureFlagsEbx.Bits.IA32_TSC_ADJUST == 1) {
532 DEBUG ((DEBUG_INFO,
"OCCPU: TSC Adjust %Lu\n", TscAdjust));
534 if (TscAdjustPtr != NULL) {
535 *TscAdjustPtr = TscAdjust;
540 if (MaxId >= CPUID_TIME_STAMP_COUNTER) {
542 CPUID_TIME_STAMP_COUNTER,
543 &CpuidDenominatorEax,
545 &CpuidARTFrequencyEcx,
548 if (CpuidARTFrequencyEcx > 0) {
549 ARTFrequency = CpuidARTFrequencyEcx;
550 DEBUG ((DEBUG_INFO,
"OCCPU: Queried Core Crystal Clock Frequency %11LuHz\n", ARTFrequency));
552 AsmCpuid (CPUID_VERSION_INFO, &CpuidVerEax.Uint32, NULL, NULL, NULL);
553 Model = (UINT8)CpuidVerEax.Bits.Model | (UINT8)(CpuidVerEax.Bits.ExtendedModelId << 4U);
572 if (ARTFrequency > 0) {
573 DEBUG ((DEBUG_INFO,
"OCCPU: Known Model Core Crystal Clock Frequency %11LuHz\n", ARTFrequency));
577 if ((CpuidDenominatorEax > 0) && (CpuidNumeratorEbx > 0)) {
582 if ((ARTFrequency == 0) && (MaxId >= CPUID_PROCESSOR_FREQUENCY)) {
584 ARTFrequency = BaseMultThenDivU64x64x32 (
590 if (ARTFrequency > 0ULL) {
593 "OCCPU: Core Crystal Clock Frequency from TSC %11LuHz = %11LuHz * %u / %u\n",
602 AsmCpuid (CPUID_PROCESSOR_FREQUENCY, &CpuidFrequencyEax.Uint32, NULL, NULL, NULL);
603 CPUFrequencyFromART =
MultU64x32 (CpuidFrequencyEax.Bits.ProcessorBaseFrequency, 1000000);
611 if (ARTFrequency == 0ULL) {
613 DEBUG ((DEBUG_INFO,
"OCCPU: Fallback Core Crystal Clock Frequency %11LuHz\n", ARTFrequency));
616 ASSERT (ARTFrequency > 0ULL);
617 if (CPUFrequencyFromART == 0ULL) {
618 CPUFrequencyFromART = BaseMultThenDivU64x64x32 (
626 ASSERT (CPUFrequencyFromART > 0ULL);
629 "OCCPU: CPUFrequencyFromART %11LuHz %5LuMHz = %Lu * %u / %u\n",
631 DivU64x32 (CPUFrequencyFromART, 1000000),
641 *CPUFrequency = CPUFrequencyFromART;
647 OUT UINT64 *FSBFrequency OPTIONAL,
648 OUT BOOLEAN *UnderHypervisor OPTIONAL
655 CPUID_VERSION_INFO_ECX CpuidVerEcx;
668 if (FSBFrequency != NULL) {
672 if (UnderHypervisor != NULL) {
673 *UnderHypervisor = CpuidVerEcx.Bits.ParaVirtualized != 0;
681 if (CpuidVerEcx.Bits.ParaVirtualized == 0) {
700 AsmCpuid (0x40000000, &CpuidEax, &CpuidEbx, &CpuidEcx, &CpuidEdx);
702 CopyMem (&HvVendor[0], &CpuidEbx,
sizeof (UINT32));
703 CopyMem (&HvVendor[4], &CpuidEcx,
sizeof (UINT32));
704 CopyMem (&HvVendor[8], &CpuidEdx,
sizeof (UINT32));
707 if (AsciiStrCmp (HvVendor,
"Microsoft Hv") == 0) {
712 if (FSBFrequency != NULL) {
723 if (AsciiStrCmp (HvVendor,
"XenVMMXenVMM") == 0) {
726 AsmCpuidEx (0x40000003, 0, NULL, NULL, &CpuidEcx, NULL);
727 if (FSBFrequency != NULL) {
728 *FSBFrequency = 100000000;
731 return CpuidEcx * 1000ULL;
737 if (CpuidEax < 0x40000010) {
741 AsmCpuid (0x40000010, &CpuidEax, &CpuidEbx, NULL, NULL);
742 if ((CpuidEax == 0) || (CpuidEbx == 0)) {
749 if (FSBFrequency != NULL) {
750 *FSBFrequency = CpuidEbx * 1000ULL;
753 return CpuidEax * 1000ULL;
775 if (CPUFrequency == 0) {
777 if (CPUFrequency == 0) {
779 if (CPUFrequency == 0) {
781 if (CPUFrequency == 0) {
EFI_GUID gEfiAcpiDescriptionGuid
EFI_GUID gAppleFsbFrequencyPlatformInfoIndexHobGuid
#define CPUID_VENDOR_INTEL
UINT64 OcGetTSCFrequency(VOID)
UINTN InternalGetPmTimerAddr(OUT CONST CHAR8 **Type OPTIONAL)
STATIC UINT64 InternalSelectAppleFsbFrequency(IN UINT64 *FsbFrequency, IN UINT32 FsbFrequncyCount)
UINT64 InternalCalculateVMTFrequency(OUT UINT64 *FSBFrequency OPTIONAL, OUT BOOLEAN *UnderHypervisor OPTIONAL)
UINT64 InternalCalculateARTFrequencyIntel(OUT UINT64 *CPUFrequency, OUT UINT64 *TscAdjustPtr OPTIONAL, IN BOOLEAN Recalculate)
UINT64 InternalCalculateTSCFromApplePlatformInfo(OUT UINT64 *FSBFrequency OPTIONAL, IN BOOLEAN Recalculate)
UINT64 InternalCalculateTSCFromPMTimer(IN BOOLEAN Recalculate)
#define B_ICH_PMC_BAR2_BASE_BAR
#define B_ICH_PMC_ACPI_BASE_BAR
#define V_CHT_PMC_PCI_DEVICE_ID
Intel Bay-Trail/Cherry-Trail PMC device-id.
#define PCI_ICH_PMC_ADDRESS(Register)
Macro to generate the PCI address of any given ICH PMC Register.
#define R_ICH_LPC_ACPI_BASE
#define R_ICH_PMC_BAR2_BASE
#define B_PIIX4_PMREGMISC_PMIOSE
#define B_PIIX4_PM_BASE_BAR
#define R_AMD_ACPI_PM_TMR_BLOCK
AcpiPmTmrBlk (3-289)
#define B_ICH_PMC_BAR2_BASE_BAR_EN
#define R_AMD_ACPI_MMIO_BASE
AcpiMMioAddr (3-268)
#define R_PIIX4_PMREGMISC
See PMIOSE.
#define R_ICH_PMC_ACPI_BASE
#define PCI_ICH_LPC_ADDRESS(Register)
Macro to generate the PCI address of any given ICH LPC Register.
#define B_ICH_LPC_ACPI_CNTL_ACPI_EN
#define R_AMD_ACPI_MMIO_PMIO_BASE
PMIO (3-268)
#define V_ACPI_TMR_FREQUENCY
#define B_ICH_PMC_ACPI_CNTL_ACPI_EN
#define V_VLV_PMC_PCI_DEVICE_ID
Intel Valley View PMC device-id.
#define PCI_PIIX4_PMC_ADDRESS(Register)
Macro to generate the PCI address of any given PIIX4 PMC Register.
#define V_PIIX4_PMC_PCI_DEVICE_ID
Intel PIIX4 PMC device-id.
#define V_ICH_PCI_VENDOR_ID
Intel vendor-id.
#define R_BRSW_PMC_ACPI_BASE
#define R_ICH_PMC_ACPI_CNTL
#define B_ICH_LPC_ACPI_BASE_BAR
#define R_ICH_LPC_ACPI_CNTL
#define B_BRSW_PMC_ACPI_BASE_BAR
#define B_NVIDIA_MCP_MC_BASE
#define R_NVIDIA_MCP_MC_UN78
#define R_NVIDIA_MCP89_DDR_PLL
#define R_NVIDIA_MCP_MC_UN44
#define V_NVIDIA_MCP_MC_VENDOR
#define NVIDIA_MCP79_GET_FSB_FREQUENCY_DIVIDEND(Un44, Un78)
#define NVIDIA_MCP79_GET_FSB_FREQUENCY_DIVISOR(Un44, Un78)
VOID EFIAPI AsmMeasureTicks(IN UINT32 AcpiTicksDuration, IN UINT16 TimerAddr, OUT UINT32 *AcpiTicksDelta, OUT UINT64 *TscTicksDelta)
DMG_SIZE_DEVICE_PATH Size
UINT64 InternalConvertAppleFSBToTSCFrequency(IN UINT64 FSBFrequency)
#define OC_FALLBACK_CPU_FREQUENCY
EFI_STATUS OcReadApplePlatformFirstDataAlloc(IN APPLE_PLATFORM_INFO_DATABASE_PROTOCOL *PlatformInfo, IN EFI_GUID *DataGuid, OUT UINT32 *Size, OUT VOID **Data)
EFI_STATUS OcReadApplePlatformFirstData(IN APPLE_PLATFORM_INFO_DATABASE_PROTOCOL *PlatformInfo, IN EFI_GUID *DataGuid, IN OUT UINT32 *Size, OUT VOID *Data)
EFI_STATUS OcReadApplePlatformData(IN APPLE_PLATFORM_INFO_DATABASE_PROTOCOL *PlatformInfo, IN EFI_GUID *DataGuid, IN EFI_GUID *HobGuid, IN OUT UINT32 *Size, OUT VOID *Data)
EFI_GUID gOcVendorVariableGuid
#define OC_ACPI_CPU_FREQUENCY_VARIABLE_NAME
#define SERVER_ART_CLOCK_SOURCE
#define CPU_MODEL_SKYLAKE_DT
#define CPU_MODEL_DENVERTON
Goldmont Microserver.
#define CLIENT_ART_CLOCK_SOURCE
#define DEFAULT_ART_CLOCK_SOURCE
#define CPU_MODEL_SKYLAKE
Skylake-S.
#define CPU_MODEL_GOLDMONT
Apollo Lake.
#define CPU_MODEL_KABYLAKE_DT
#define CPU_MODEL_KABYLAKE
Kabylake Dektop.
#define ATOM_ART_CLOCK_SOURCE
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_RUNTIME_SERVICES * gRT
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
UINT32 AsmCpuid(IN UINT32 Index, OUT UINT32 *Eax, OPTIONAL OUT UINT32 *Ebx, OPTIONAL OUT UINT32 *Ecx, OPTIONAL OUT UINT32 *Edx OPTIONAL)
UINT32 AsmCpuidEx(IN UINT32 Index, IN UINT32 SubIndex, OUT UINT32 *Eax, OPTIONAL OUT UINT32 *Ebx, OPTIONAL OUT UINT32 *Ecx, OPTIONAL OUT UINT32 *Edx OPTIONAL)
VOID EFIAPI EnableInterrupts(VOID)
UINT64 EFIAPI AsmReadMsr64(IN UINT32 Index)
UINT16 EFIAPI MmioRead16(IN UINTN Address)
UINT32 EFIAPI MmioRead32(IN UINTN Address)
UINT16 EFIAPI AsmReadCs(VOID)
UINT32 EFIAPI IoRead32(IN UINTN Port)
#define DivU64x32(x, y, z)
EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE PM_TMR_BLK