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:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user