From 5c42665070968193cb609ef0f55c22d8cf1cc659 Mon Sep 17 00:00:00 2001 From: Shaneee Date: Wed, 11 Sep 2024 15:12:18 +0100 Subject: [PATCH] OcCpuLib: Add support for AMD_CPU_EXT_FAMILY_1AH (#557) --- .../Intel/IndustryStandard/ProcessorInfo.h | 1 + Library/OcAppleKernelLib/CpuidPatches.c | 13 ++++++-- Library/OcCpuLib/OcCpuLib.c | 31 +++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/Include/Intel/IndustryStandard/ProcessorInfo.h b/Include/Intel/IndustryStandard/ProcessorInfo.h index a2931e536c0..395ac4449ee 100644 --- a/Include/Intel/IndustryStandard/ProcessorInfo.h +++ b/Include/Intel/IndustryStandard/ProcessorInfo.h @@ -258,6 +258,7 @@ typedef enum { #define AMD_CPU_EXT_FAMILY_16H 0x7 #define AMD_CPU_EXT_FAMILY_17H 0x8 #define AMD_CPU_EXT_FAMILY_19H 0xA +#define AMD_CPU_EXT_FAMILY_1AH 0x1A // CPU_P_STATE_COORDINATION /// P-State Coordination diff --git a/Library/OcAppleKernelLib/CpuidPatches.c b/Library/OcAppleKernelLib/CpuidPatches.c index a9af9edefd8..2723a1e1bb3 100644 --- a/Library/OcAppleKernelLib/CpuidPatches.c +++ b/Library/OcAppleKernelLib/CpuidPatches.c @@ -1646,15 +1646,22 @@ PatchProvideCurrentCpuInfo ( // Perform TSC and FSB calculations. This is traditionally done in tsc.c in XNU. // // For AMD Processors - if ((CpuInfo->Family == 0xF) && ((CpuInfo->ExtFamily == 0x8) || (CpuInfo->ExtFamily == 0xA))) { + if ((CpuInfo->Family == 0xF) && ((CpuInfo->ExtFamily == 0x8) || (CpuInfo->ExtFamily == 0xA) || (CpuInfo->ExtFamily == 0xB))) { DEBUG ((DEBUG_INFO, "OCAK: Setting FSB and TSC for Family 0x%x and ExtFamily 0x%x\n", (UINT16)CpuInfo->Family, (UINT16)CpuInfo->ExtFamily)); - busFreqValue = CpuInfo->FSBFrequency; + busFreqValue = CpuInfo->FSBFrequency; + + // Handle case where FSBFrequency is zero, providing a fallback + if (busFreqValue == 0) { + busFreqValue = 100000000; // Assume 100 MHz FSB as fallback + DEBUG ((DEBUG_WARN, "OCAK: FSBFrequency is zero, using fallback value: 100 MHz\n")); + } + busFCvtt2nValue = DivU64x64Remainder ((1000000000ULL << 32), busFreqValue, NULL); busFCvtn2tValue = DivU64x64Remainder ((1000000000ULL << 32), busFCvtt2nValue, NULL); tscFreqValue = CpuInfo->CPUFrequency; tscFCvtt2nValue = DivU64x64Remainder ((1000000000ULL << 32), tscFreqValue, NULL); - tscFCvtn2tValue = DivU64x64Remainder ((1000000000ULL << 32), tscFCvtt2nValue, NULL); + tscFCvtn2tValue = DivU64x64Remainder ((1000000000ULL << 32), tscFCvtt2nValue, NULL); } // For all other processors else { diff --git a/Library/OcCpuLib/OcCpuLib.c b/Library/OcCpuLib/OcCpuLib.c index 3297fa8256c..42b445b7407 100644 --- a/Library/OcCpuLib/OcCpuLib.c +++ b/Library/OcCpuLib/OcCpuLib.c @@ -690,6 +690,35 @@ ScanAmdProcessor ( MaxBusRatio = 0; switch (Cpu->ExtFamily) { + case AMD_CPU_EXT_FAMILY_1AH: + if (Cpu->CPUFrequencyFromVMT == 0) { + CofVid = AsmReadMsr64 (K10_PSTATE_STATUS); + CoreFrequencyID = (UINT8)BitFieldRead64 (CofVid, 0, 11); // 12-bit field for FID + + // On AMD Family 1Ah and later, if the Frequency ID (FID) exceeds 0x0f, + // the core frequency is scaled by a factor of 5. This scaling behavior + // is based on Linux kernel logic for handling higher frequency multipliers + // in newer AMD CPUs, where the FID no longer directly correlates to the + // bus ratio. + if (CoreFrequencyID > 0x0f) { + CoreFrequencyID *= 5; + } + + MaxBusRatio = (UINT8)(CoreFrequencyID); + } + + // + // Get core count from CPUID + // + if (Cpu->MaxExtId >= 0x8000001E) { + AsmCpuid (0x8000001E, NULL, &CpuidEbx, NULL, NULL); + Cpu->CoreCount = (UINT16)DivU64x32 ( + Cpu->ThreadCount, + (BitFieldRead32 (CpuidEbx, 8, 15) + 1) + ); + } + + break; case AMD_CPU_EXT_FAMILY_17H: case AMD_CPU_EXT_FAMILY_19H: if (Cpu->CPUFrequencyFromVMT == 0) { @@ -785,6 +814,8 @@ ScanAmdProcessor ( // if (MaxBusRatio == 0) { Cpu->FSBFrequency = 100000000; // 100 MHz like Intel part. + } else if (Cpu->ExtFamily == AMD_CPU_EXT_FAMILY_1AH) { + Cpu->FSBFrequency = DivU64x32 (Cpu->CPUFrequency, CoreFrequencyID); // No divisor for Family 1Ah } else { Cpu->FSBFrequency = DivU64x32 (Cpu->CPUFrequency, MaxBusRatio); }