From 4106e3f1466fb5e49230cca1a33de549809da7a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Fri, 18 Sep 2020 19:45:56 +0200 Subject: [PATCH] kernel/x86: rework get_frequency_for MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit we don't sample if the last sample is too recent and use the cached result. Change-Id: I17ed29bda7fe7276f1a4148b3e1985c9d32ae032 Reviewed-on: https://review.haiku-os.org/c/haiku/+/4101 Reviewed-by: Jérôme Duval Reviewed-by: Adrien Destugues --- headers/private/kernel/arch/x86/arch_cpu.h | 5 +++++ src/system/kernel/arch/x86/arch_cpu.cpp | 6 ++++++ .../kernel/arch/x86/arch_system_info.cpp | 21 +++++++++++++------ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index 2ba90b0551..3b0b60fa9c 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -518,6 +518,11 @@ typedef struct arch_cpu_info { uint32 logical_apic_id; + uint64 mperf_prev; + uint64 aperf_prev; + bigtime_t perf_timestamp; + uint64 frequency; + struct X86PagingStructures* active_paging_structures; size_t dr6; // temporary storage for debug registers (cf. diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 58337eae55..20c9c76515 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -1425,6 +1425,12 @@ arch_cpu_init_percpu(kernel_args* args, int cpu) x86_write_msr(IA32_MSR_TSC_AUX, cpu); #endif + if (x86_check_feature(IA32_FEATURE_APERFMPERF, FEATURE_6_ECX)) { + gCPU[cpu].arch.mperf_prev = x86_read_msr(IA32_MSR_MPERF); + gCPU[cpu].arch.aperf_prev = x86_read_msr(IA32_MSR_APERF); + gCPU[cpu].arch.frequency = 0; + gCPU[cpu].arch.perf_timestamp = 0; + } return __x86_patch_errata_percpu(cpu); } diff --git a/src/system/kernel/arch/x86/arch_system_info.cpp b/src/system/kernel/arch/x86/arch_system_info.cpp index c162ed2a64..0d8d0af3b8 100644 --- a/src/system/kernel/arch/x86/arch_system_info.cpp +++ b/src/system/kernel/arch/x86/arch_system_info.cpp @@ -135,22 +135,31 @@ arch_fill_topology_node(cpu_topology_node_info* node, int32 cpu) static void -get_frequency_for(void *_frequency, int /*cpu*/) +get_frequency_for(void *_frequency, int cpu) { uint64 *frequency = (uint64*)_frequency; - uint64 mperf = x86_read_msr(IA32_MSR_MPERF); - uint64 aperf = x86_read_msr(IA32_MSR_APERF); - for (int i = 0; i < 1000; i++) - arch_cpu_pause(); + bigtime_t timestamp = gCPU[cpu].arch.perf_timestamp; + bigtime_t timestamp2 = system_time(); + if (timestamp2 - timestamp < 100) { + *frequency = gCPU[cpu].arch.frequency; + return; + } + uint64 mperf = gCPU[cpu].arch.mperf_prev; + uint64 aperf = gCPU[cpu].arch.aperf_prev; uint64 mperf2 = x86_read_msr(IA32_MSR_MPERF); uint64 aperf2 = x86_read_msr(IA32_MSR_APERF); if (mperf2 == mperf) *frequency = 0; - else + else { *frequency = (aperf2 - aperf) * sCPUClockSpeed / (mperf2 - mperf); + gCPU[cpu].arch.mperf_prev = mperf2; + gCPU[cpu].arch.aperf_prev = aperf2; + gCPU[cpu].arch.perf_timestamp = timestamp2; + gCPU[cpu].arch.frequency = *frequency; + } }