kernel/cpu: add cpu_frequency()

implement on x86 with APERFMPERF.

Change-Id: Ia484854c76dee76c5447983de15800a25d791d39
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3213
Reviewed-by: Jérôme Duval <[email protected]>
This commit is contained in:
Jérôme Duval
2020-09-15 20:42:14 +00:00
parent 026c8b9c04
commit 22fdfc4428
10 changed files with 94 additions and 0 deletions
@@ -19,6 +19,8 @@ extern "C" {
status_t arch_system_info_init(struct kernel_args *args);
void arch_fill_topology_node(cpu_topology_node_info* node, int32 cpu);
status_t arch_get_frequency(uint64 *frequency, int32 cpu);
#ifdef __cplusplus
}
+1
View File
@@ -102,6 +102,7 @@ status_t cpu_init_percpu(struct kernel_args *ka, int curr_cpu);
status_t cpu_init_post_vm(struct kernel_args *args);
status_t cpu_init_post_modules(struct kernel_args *args);
bigtime_t cpu_get_active_time(int32 cpu);
uint64 cpu_frequency(int32 cpu);
cpu_ent *get_cpu_struct(void);
extern inline cpu_ent *get_cpu_struct(void) { return &gCPU[smp_get_current_cpu()]; }
@@ -54,3 +54,12 @@ arch_system_info_init(struct kernel_args *args)
{
return B_OK;
}
status_t
arch_get_frequency(uint64 *frequency, int32 cpu)
{
*frequency = 0;
return B_OK;
}
@@ -27,3 +27,11 @@ arch_system_info_init(struct kernel_args *args)
{
return B_OK;
}
status_t
arch_get_frequency(uint64 *frequency, int32 cpu)
{
*frequency = 0;
return B_OK;
}
@@ -57,3 +57,11 @@ arch_system_info_init(struct kernel_args *args)
return B_OK;
}
status_t
arch_get_frequency(uint64 *frequency, int32 cpu)
{
*frequency = sCPUClockFrequency;
return B_OK;
}
@@ -110,3 +110,11 @@ arch_system_info_init(struct kernel_args *args)
return B_OK;
}
status_t
arch_get_frequency(uint64 *frequency, int32 cpu)
{
*frequency = sCPUClockFrequency;
return B_OK;
}
@@ -33,3 +33,10 @@ arch_system_info_init(struct kernel_args *args)
return B_OK;
}
status_t
arch_get_frequency(uint64 *frequency, int32 cpu)
{
*frequency = sCPUClockFrequency;
return B_OK;
}
@@ -33,3 +33,10 @@ arch_system_info_init(struct kernel_args *args)
return B_OK;
}
status_t
arch_get_frequency(uint64 *frequency, int32 cpu)
{
*frequency = sCPUClockFrequency;
return B_OK;
}
@@ -131,6 +131,38 @@ arch_fill_topology_node(cpu_topology_node_info* node, int32 cpu)
}
static void
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();
uint64 mperf2 = x86_read_msr(IA32_MSR_MPERF);
uint64 aperf2 = x86_read_msr(IA32_MSR_APERF);
if (mperf2 == mperf)
*frequency = 0;
else
*frequency = (aperf2 - aperf) * sCPUClockSpeed / (mperf2 - mperf);
}
status_t
arch_get_frequency(uint64 *frequency, int32 cpu)
{
if (x86_check_feature(IA32_FEATURE_APERFMPERF, FEATURE_6_ECX))
call_single_cpu_sync(cpu, get_frequency_for, frequency);
else
*frequency = sCPUClockSpeed;
return B_OK;
}
// #pragma mark -
+12
View File
@@ -12,6 +12,7 @@
#include <cpu.h>
#include <arch/cpu.h>
#include <arch/system_info.h>
#include <string.h>
@@ -171,6 +172,17 @@ cpu_get_active_time(int32 cpu)
}
uint64
cpu_frequency(int32 cpu)
{
if (cpu < 0 || cpu >= smp_get_num_cpus())
return 0;
uint64 frequency = 0;
arch_get_frequency(&frequency, cpu);
return frequency;
}
void
clear_caches(void *address, size_t length, uint32 flags)
{