amd_pstates: introduce a AMD P-states driver for Ryzen with the CPPC feature
tested on Zen2 (Ryzen 3 5300U) This support was submitted in October for inclusion in Linux. Haiku supports only two profiles. We could probably add some more, and let the driver says which it supports. Change-Id: Id7754b445bc32a691d58a1e4af630351562abc22 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5826 Reviewed-by: waddlesplash <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
@@ -48,7 +48,7 @@ AddFilesToPackage add-ons kernel generic
|
|||||||
AddFilesToPackage add-ons kernel partitioning_systems
|
AddFilesToPackage add-ons kernel partitioning_systems
|
||||||
: amiga_rdb@m68k apple@ppc sun@sparc efi_gpt intel session ;
|
: amiga_rdb@m68k apple@ppc sun@sparc efi_gpt intel session ;
|
||||||
AddFilesToPackage add-ons kernel interrupt_controllers : openpic@ppc ;
|
AddFilesToPackage add-ons kernel interrupt_controllers : openpic@ppc ;
|
||||||
AddFilesToPackage add-ons kernel power cpufreq : intel_pstates@x86,x86_64 ;
|
AddFilesToPackage add-ons kernel power cpufreq : amd_pstates@x86,x86_64 intel_pstates@x86,x86_64 ;
|
||||||
AddFilesToPackage add-ons kernel power cpuidle : intel_cstates@x86,x86_64 ;
|
AddFilesToPackage add-ons kernel power cpuidle : intel_cstates@x86,x86_64 ;
|
||||||
|
|
||||||
if $(TARGET_ARCH) = x86 || $(TARGET_ARCH) = x86_64 {
|
if $(TARGET_ARCH) = x86 || $(TARGET_ARCH) = x86_64 {
|
||||||
|
|||||||
@@ -129,6 +129,24 @@
|
|||||||
#define MSR_F10H_DE_CFG 0xc0011029
|
#define MSR_F10H_DE_CFG 0xc0011029
|
||||||
#define DE_CFG_SERIALIZE_LFENCE (1 << 1)
|
#define DE_CFG_SERIALIZE_LFENCE (1 << 1)
|
||||||
|
|
||||||
|
#define MSR_AMD_CPPC_CAP1 0xc00102b0
|
||||||
|
#define AMD_CPPC_LOWEST_PERF(x) ((x) & 0xff)
|
||||||
|
#define AMD_CPPC_LOWNONLIN_PERF(x) ((x >> 8) & 0xff)
|
||||||
|
#define AMD_CPPC_NOMINAL_PERF(x) ((x >> 16) & 0xff)
|
||||||
|
#define AMD_CPPC_HIGHEST_PERF(x) ((x >> 24) & 0xff)
|
||||||
|
#define MSR_AMD_CPPC_ENABLE 0xc00102b1
|
||||||
|
#define MSR_AMD_CPPC_REQ 0xc00102b3
|
||||||
|
#define AMD_CPPC_MAX_PERF(x) ((x) & 0xff)
|
||||||
|
#define AMD_CPPC_MIN_PERF(x) (((x) & 0xff) << 8)
|
||||||
|
#define AMD_CPPC_DES_PERF(x) (((x) & 0xff) << 16)
|
||||||
|
#define AMD_CPPC_EPP_PERF(x) (((x) & 0xff) << 24)
|
||||||
|
|
||||||
|
#define AMD_CPPC_EPP_PERFORMANCE 0x00
|
||||||
|
#define AMD_CPPC_EPP_BALANCE_PERFORMANCE 0x80
|
||||||
|
#define AMD_CPPC_EPP_BALANCE_POWERSAVE 0xbf
|
||||||
|
#define AMD_CPPC_EPP_POWERSAVE 0xff
|
||||||
|
#define MSR_AMD_CPPC_STATUS 0xc00102b4
|
||||||
|
|
||||||
|
|
||||||
// Hardware P-States MSR registers §14.4.1
|
// Hardware P-States MSR registers §14.4.1
|
||||||
// reference https://software.intel.com/content/dam/develop/public/us/en/documents/253669-sdm-vol-3b.pdf
|
// reference https://software.intel.com/content/dam/develop/public/us/en/documents/253669-sdm-vol-3b.pdf
|
||||||
@@ -359,6 +377,7 @@
|
|||||||
#define IA32_FEATURE_AMD_SSBD (1 << 24) // Speculative Store Bypass Disable
|
#define IA32_FEATURE_AMD_SSBD (1 << 24) // Speculative Store Bypass Disable
|
||||||
#define IA32_FEATURE_VIRT_SSBD (1 << 25) // Virtualized Speculative Store Bypass Disable
|
#define IA32_FEATURE_VIRT_SSBD (1 << 25) // Virtualized Speculative Store Bypass Disable
|
||||||
#define IA32_FEATURE_AMD_SSB_NO (1 << 26) // Speculative Store Bypass is fixed in hardware
|
#define IA32_FEATURE_AMD_SSB_NO (1 << 26) // Speculative Store Bypass is fixed in hardware
|
||||||
|
#define IA32_FEATURE_CPPC (1 << 27) // Collaborative Processor Performance Control
|
||||||
|
|
||||||
|
|
||||||
// Memory type ranges
|
// Memory type ranges
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel power cpufreq ;
|
SubDir HAIKU_TOP src add-ons kernel power cpufreq ;
|
||||||
|
|
||||||
|
SubInclude HAIKU_TOP src add-ons kernel power cpufreq amd_pstates ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel power cpufreq intel_pstates ;
|
SubInclude HAIKU_TOP src add-ons kernel power cpufreq intel_pstates ;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
SubDir HAIKU_TOP src add-ons kernel power cpufreq amd_pstates ;
|
||||||
|
|
||||||
|
UsePrivateKernelHeaders ;
|
||||||
|
|
||||||
|
KernelAddon amd_pstates :
|
||||||
|
amd_pstates.cpp
|
||||||
|
;
|
||||||
|
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020-2022, Jérôme Duval, [email protected].
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <cpufreq.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
#include <arch_cpu.h>
|
||||||
|
#include <cpu.h>
|
||||||
|
#include <smp.h>
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define AMD_PSTATES_MODULE_NAME CPUFREQ_MODULES_PREFIX "/amd_pstates/v1"
|
||||||
|
|
||||||
|
|
||||||
|
static uint32 sHWPLowest;
|
||||||
|
static uint32 sHWPGuaranteed;
|
||||||
|
static uint32 sHWPEfficient;
|
||||||
|
static uint32 sHWPHighest;
|
||||||
|
|
||||||
|
static bool sAvoidBoost = true;
|
||||||
|
|
||||||
|
|
||||||
|
static void set_normal_pstate(void* /* dummy */, int cpu);
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
pstates_set_scheduler_mode(scheduler_mode mode)
|
||||||
|
{
|
||||||
|
sAvoidBoost = mode == SCHEDULER_MODE_POWER_SAVING;
|
||||||
|
call_all_cpus(set_normal_pstate, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
pstates_increase_performance(int delta)
|
||||||
|
{
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
pstates_decrease_performance(int delta)
|
||||||
|
{
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_cpu_model_supported(cpu_ent* cpu)
|
||||||
|
{
|
||||||
|
if (cpu->arch.vendor != VENDOR_AMD)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_normal_pstate(void* /* dummy */, int cpu)
|
||||||
|
{
|
||||||
|
x86_write_msr(MSR_AMD_CPPC_ENABLE, 1);
|
||||||
|
|
||||||
|
uint64 cap1 = x86_read_msr(MSR_AMD_CPPC_CAP1);
|
||||||
|
sHWPLowest = AMD_CPPC_LOWEST_PERF(cap1);
|
||||||
|
sHWPEfficient = AMD_CPPC_LOWNONLIN_PERF(cap1);
|
||||||
|
sHWPGuaranteed = AMD_CPPC_NOMINAL_PERF(cap1);
|
||||||
|
sHWPHighest = AMD_CPPC_HIGHEST_PERF(cap1);
|
||||||
|
|
||||||
|
uint64 request = AMD_CPPC_MIN_PERF(sHWPEfficient);
|
||||||
|
request |= AMD_CPPC_MAX_PERF(sAvoidBoost ? sHWPGuaranteed : sHWPHighest);
|
||||||
|
request |= AMD_CPPC_EPP_PERF(
|
||||||
|
sAvoidBoost ? AMD_CPPC_EPP_BALANCE_PERFORMANCE : AMD_CPPC_EPP_PERFORMANCE);
|
||||||
|
x86_write_msr(MSR_AMD_CPPC_REQ, request & 0xffffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
init_pstates()
|
||||||
|
{
|
||||||
|
if (!x86_check_feature(IA32_FEATURE_CPPC, FEATURE_EXT_8_EBX))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
int32 cpuCount = smp_get_num_cpus();
|
||||||
|
for (int32 i = 0; i < cpuCount; i++) {
|
||||||
|
if (!is_cpu_model_supported(&gCPU[i]))
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("using AMD P-States (capabilities: 0x%08" B_PRIx64 "\n",
|
||||||
|
x86_read_msr(MSR_AMD_CPPC_CAP1));
|
||||||
|
|
||||||
|
pstates_set_scheduler_mode(SCHEDULER_MODE_LOW_LATENCY);
|
||||||
|
|
||||||
|
call_all_cpus_sync(set_normal_pstate, NULL);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
uninit_pstates()
|
||||||
|
{
|
||||||
|
call_all_cpus_sync(set_normal_pstate, NULL);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
std_ops(int32 op, ...)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case B_MODULE_INIT:
|
||||||
|
return init_pstates();
|
||||||
|
|
||||||
|
case B_MODULE_UNINIT:
|
||||||
|
uninit_pstates();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static cpufreq_module_info sAMDPStates = {
|
||||||
|
{
|
||||||
|
AMD_PSTATES_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
std_ops,
|
||||||
|
},
|
||||||
|
|
||||||
|
1.0f,
|
||||||
|
|
||||||
|
pstates_set_scheduler_mode,
|
||||||
|
|
||||||
|
pstates_increase_performance,
|
||||||
|
pstates_decrease_performance,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module_info* modules[] = {
|
||||||
|
(module_info*)&sAMDPStates,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
Reference in New Issue
Block a user