kernel/x86: rework get_frequency_for

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 <jerome.duval@gmail.com>
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
Jérôme Duval 2020-09-18 19:45:56 +02:00
parent 7c2c355f17
commit 4106e3f146
3 changed files with 26 additions and 6 deletions

View File

@ -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.

View File

@ -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);
}

View File

@ -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;
}
}