From ca70ea975aa40d0a38e05e27c9ae15d6fef89e8c Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sun, 28 Mar 2021 17:12:18 +0300 Subject: [PATCH] OcCpuLib: Improve CPU frequency detection on nForce MPC79 closes acidanthera/bugtracker#1576 --- Docs/Configuration.tex | 1 + .../IndustryStandard/MpcMemoryController.h | 42 +++++++ Library/OcCpuLib/FrequencyDetect.c | 116 ++++++++++++------ OpenCorePkg.dec | 6 + 4 files changed, 126 insertions(+), 39 deletions(-) create mode 100644 Include/Nvidia/IndustryStandard/MpcMemoryController.h diff --git a/Docs/Configuration.tex b/Docs/Configuration.tex index 750009b6..e4962dc2 100755 --- a/Docs/Configuration.tex +++ b/Docs/Configuration.tex @@ -656,6 +656,7 @@ Add \texttt{.clang\_complete} file with similar content to the UDK root: -I/UefiPackages/OpenCorePkg/Include/Generic -I/UefiPackages/OpenCorePkg/Include/Intel -I/UefiPackages/OpenCorePkg/Include/Microsoft +-I/UefiPackages/OpenCorePkg/Include/Nvidia -I/UefiPackages/OpenCorePkg/Include/VMware -I/UefiPackages/OvmfPkg/Include -I/UefiPackages/UefiCpuPkg/Include diff --git a/Include/Nvidia/IndustryStandard/MpcMemoryController.h b/Include/Nvidia/IndustryStandard/MpcMemoryController.h new file mode 100644 index 00000000..f752c266 --- /dev/null +++ b/Include/Nvidia/IndustryStandard/MpcMemoryController.h @@ -0,0 +1,42 @@ +/** @file + Copyright (C) 2021, vit9696. All rights reserved.
+ SPDX-License-Identifier: BSD-3-Clause +**/ + +#ifndef NVIDIA_MPC_MEMORY_CONTROLLER_H +#define NVIDIA_MPC_MEMORY_CONTROLLER_H + +/** + I/O port to obtain current DDR frequency on NVIDIA nForce MPC89 + and possibly others. Example value: 1066666664. +**/ +#define R_NVIDIA_MPC89_DDR_PLL 0x580 + +/** + MMIO base to NVIDIA nForce MPC79 and MPC89 memory controller. +**/ +#define B_NVIDIA_MPC_MC_BASE 0xF001B000 + +/** + Common PCI identifiers for nForce MPC79 and MPC89 memory controllers. +**/ +#define V_NVIDIA_MPC_MC_VENDOR 0x10DE +#define V_NVIDIA_MPC79_MC_DEVICE 0x0A89 +#define V_NVIDIA_MPC89_MC_DEVICE 0x0D69 + +/** + MPC79 and MPC89 memory controller registers, not much is known. +**/ +#define R_NVIDIA_MPC_MC_UN44 0x44 +#define R_NVIDIA_MPC_MC_MPCC 0x48 +#define R_NVIDIA_MPC_MC_UN78 0x78 +#define R_NVIDIA_MPC_MC_MPLM 0xC8 +#define R_NVIDIA_MPC_MC_MPLN 0xC9 + +#define NVIDIA_MPC79_GET_FSB_FREQUENCY_DIVIDEND(Un44, Un78) \ + (25000000ULL * (((Un44) >> 9U) & 0xFFU) * (((Un78) >> 8U) & 0xFFU)) + +#define NVIDIA_MPC79_GET_FSB_FREQUENCY_DIVISOR(Un44, Un78) \ + (((Un44) & 0xFFU) * ((Un78) & 0xFFU) * (1 << (((Un44) >> 26U) & 3U))) + +#endif // NVIDIA_MPC_MEMORY_CONTROLLER_H diff --git a/Library/OcCpuLib/FrequencyDetect.c b/Library/OcCpuLib/FrequencyDetect.c index 6ded4c88..26f57583 100644 --- a/Library/OcCpuLib/FrequencyDetect.c +++ b/Library/OcCpuLib/FrequencyDetect.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -236,22 +237,21 @@ InternalSelectAppleFsbFrequency ( IN UINT32 FsbFrequncyCount ) { - UINT32 Freq; + UINT32 Pll; if (FsbFrequncyCount < 5) { return 0 /* Invalid */; } // - // This one is for nForce MCP89 installed in MacBook7,1. - // Not sure what it reads from. + // Tested on nForce MCP89 installed in MacBook7,1. // - Freq = IoRead32 (0x580); + Pll = IoRead32 (R_NVIDIA_MPC89_DDR_PLL); DEBUG (( DEBUG_INFO, - "OCCPU: Selecting freq by %u from %Lu %Lu %Lu %Lu %Lu\n", - Freq, + "OCCPU: Selecting FSB freq by PLL freq %u from %Lu %Lu %Lu %Lu %Lu\n", + Pll, FsbFrequency[0], FsbFrequency[1], FsbFrequency[2], @@ -259,24 +259,24 @@ InternalSelectAppleFsbFrequency ( FsbFrequency[4] )); - Freq /= 1000000; + Pll /= 1000000; - if (Freq == 16) { + if (Pll == 16) { return FsbFrequency[0]; } - if (Freq >= 1063 && Freq <= 1069) { + if (Pll >= 1063 && Pll <= 1069) { return FsbFrequency[0]; } - if (Freq >= 530 && Freq <= 536) { + if (Pll >= 530 && Pll <= 536) { return FsbFrequency[1]; } - if (Freq >= 797 && Freq <= 803) { + if (Pll >= 797 && Pll <= 803) { return FsbFrequency[2]; } - if (Freq >= 663 && Freq <= 669) { + if (Pll >= 663 && Pll <= 669) { return FsbFrequency[3]; } - if (Freq >= 1330 && Freq <= 1336) { + if (Pll >= 1330 && Pll <= 1336) { return FsbFrequency[4]; } return 0 /* Invalid */; @@ -299,6 +299,10 @@ InternalCalculateTSCFromApplePlatformInfo ( APPLE_PLATFORM_INFO_DATABASE_PROTOCOL *PlatformInfo; UINT32 Size; UINT64 *FsbFreqs; + UINT32 Un44; + UINT32 Un78; + UINT64 Dividend; + UINT32 Divisor; if (Recalculate) { ObtainedFreqs = FALSE; @@ -315,26 +319,25 @@ InternalCalculateTSCFromApplePlatformInfo ( NULL, (VOID **) &PlatformInfo ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_VERBOSE, "OCCPU: Failed to locate ApplePlatformInfo protocol - %r\n", Status)); - return 0; - } - - Status = OcReadApplePlatformFirstData ( - PlatformInfo, - &gAppleFsbFrequencyPlatformInfoGuid, - &Size, - &FsbFreq - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "OCCPU: Failed to get FSBFrequency first data - %r, trying HOB method\n", Status)); - Status = OcReadApplePlatformData ( + if (!EFI_ERROR (Status)) { + Status = OcReadApplePlatformFirstData ( PlatformInfo, &gAppleFsbFrequencyPlatformInfoGuid, - &gAppleFsbFrequencyPlatformInfoIndexHobGuid, &Size, &FsbFreq ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "OCCPU: Failed to get FSBFrequency first data - %r, trying HOB method\n", Status)); + Status = OcReadApplePlatformData ( + PlatformInfo, + &gAppleFsbFrequencyPlatformInfoGuid, + &gAppleFsbFrequencyPlatformInfoIndexHobGuid, + &Size, + &FsbFreq + ); + } + if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "OCCPU: Failed to get FSBFrequency data using HOB method - %r, trying legacy\n", Status)); Status = OcReadApplePlatformFirstDataAlloc ( @@ -343,21 +346,56 @@ InternalCalculateTSCFromApplePlatformInfo ( &Size, (VOID **) &FsbFreqs ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "OCCPU: Failed to get FSBFrequency data using legacy method - %r\n", Status)); - return 0; - } + if (!EFI_ERROR (Status)) { + if (Size >= sizeof (UINT64) && Size % sizeof (UINT64) == 0) { + FsbFreq = InternalSelectAppleFsbFrequency (FsbFreqs, Size / sizeof (UINT64)); + } else { + DEBUG ((DEBUG_INFO, "OCCPU: Invalid FSBFrequency list size %u - %r\n", Size, Status)); + Status = EFI_INVALID_PARAMETER; + } - if (Size < sizeof (UINT64) || Size % sizeof (UINT64) != 0) { - DEBUG ((DEBUG_INFO, "OCCPU: Invalid FSBFrequency list size %u - %r\n", Size, Status)); FreePool (FsbFreqs); - return 0; } - - FsbFreq = InternalSelectAppleFsbFrequency (FsbFreqs, Size / sizeof (UINT64)); - - FreePool (FsbFreqs); } + } else { + DEBUG ((DEBUG_VERBOSE, "OCCPU: Failed to locate ApplePlatformInfo protocol - %r\n", Status)); + } + + // + // This is not necessarily Apple, but keep it here for the time being. + // Should work on more or less any MPC79 device. + // + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "OCCPU: Failed to get FSBFrequency data using Apple Platform Info - %r\n", Status)); + + if (MmioRead16 (B_NVIDIA_MPC_MC_BASE) == V_NVIDIA_MPC_MC_VENDOR) { + Un44 = MmioRead32 (B_NVIDIA_MPC_MC_BASE + R_NVIDIA_MPC_MC_UN44); + Un78 = MmioRead32 (B_NVIDIA_MPC_MC_BASE + R_NVIDIA_MPC_MC_UN78); + + Dividend = NVIDIA_MPC79_GET_FSB_FREQUENCY_DIVIDEND (Un44, Un78); + Divisor = NVIDIA_MPC79_GET_FSB_FREQUENCY_DIVISOR (Un44, Un78); + + DEBUG (( + DEBUG_INFO, + "OCCPU: Found nForce MPC MC 0x%08X (UN44 0x%08X, UN78 0x%08X, DVD 0x%016Lx, DIV 0x%08X)\n", + MmioRead32 (B_NVIDIA_MPC_MC_BASE), + Un44, + Un78, + Dividend, + Divisor + )); + + if (Divisor != 0) { + FsbFreq = DivU64x32 (Dividend, Divisor); + if (FsbFreq != 0) { + Status = EFI_SUCCESS; + } + } + } + } + + if (EFI_ERROR (Status)) { + return 0; } TscFreq = InternalConvertAppleFSBToTSCFrequency (FsbFreq); diff --git a/OpenCorePkg.dec b/OpenCorePkg.dec index a7c36ed8..c308ab94 100755 --- a/OpenCorePkg.dec +++ b/OpenCorePkg.dec @@ -26,6 +26,7 @@ Include/Generic Include/Intel Include/Microsoft + Include/Nvidia Include/VMware [Includes.AArch64] @@ -35,6 +36,7 @@ # Include/Generic/AArch64 # Include/Intel/AArch64 # Include/Microsoft/AArch64 + # Include/Nvidia/AArch64 # Include/VMware/AArch64 [Includes.Arm] @@ -44,6 +46,7 @@ # Include/Generic/Arm # Include/Intel/Arm # Include/Microsoft/Arm + # Include/Nvidia/Arm # Include/VMware/Arm [Includes.Ebc] @@ -53,6 +56,7 @@ # Include/Generic/Ebc # Include/Intel/Ebc # Include/Microsoft/Ebc + # Include/Nvidia/Ebc # Include/VMware/Ebc [Includes.Ia32] @@ -62,6 +66,7 @@ # Include/Generic/Ia32 # Include/Intel/Ia32 # Include/Microsoft/Ia32 + # Include/Nvidia/Ia32 # Include/VMware/Ia32 [Includes.X64] @@ -71,6 +76,7 @@ # Include/Generic/X64 # Include/Intel/X64 # Include/Microsoft/X64 + # Include/Nvidia/X64 # Include/VMware/X64 [Guids]