From 17945bda1c73e6543213739c62d6fe26f9dce883 Mon Sep 17 00:00:00 2001 From: Kanata9020 <270539432+Kanata9020@users.noreply.github.com> Date: Wed, 21 Oct 2026 13:04:31 +0900 Subject: [PATCH 1/2] x86_64: add get_min_cpu_freq to Dvfs --- awkernel_lib/src/arch/x86_64/dvfs.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/awkernel_lib/src/arch/x86_64/dvfs.rs b/awkernel_lib/src/arch/x86_64/dvfs.rs index 7352d1bc9..3583288bb 100644 --- a/awkernel_lib/src/arch/x86_64/dvfs.rs +++ b/awkernel_lib/src/arch/x86_64/dvfs.rs @@ -13,6 +13,8 @@ use super::X86; mod hwpstate_intel; const MSR_PLATFORM_INFO: u32 = 0xCE; +const MSR_PLATFORM_INFO_MAX_OFFSET: u32 = 8; +const MSR_PLATFORM_INFO_MIN_OFFSET: u32 = 40; const IA32_PERF_MPERF: u32 = 0xE7; const IA32_PERF_APERF: u32 = 0xE8; const IA32_PERF_CTL: u32 = 0x199; @@ -53,13 +55,24 @@ impl Dvfs for X86 { fn get_max_cpu_freq() -> Result { unsafe { let platform_info = Msr::new(MSR_PLATFORM_INFO); - let max_ratio = (platform_info.read() >> 8) & 0xFF; + let max_ratio = (platform_info.read() >> MSR_PLATFORM_INFO_MAX_OFFSET) & 0xFF; let bus_freq_mhz = (__cpuid(0x16).ecx & 0xffff) as u64; Ok(max_ratio * bus_freq_mhz) } } + /// Get the minimum frequency of the current CPU. + fn get_min_cpu_freq() -> Result { + unsafe { + let platform_info = Msr::new(MSR_PLATFORM_INFO); + let min_ratio = (platform_info.read() >> MSR_PLATFORM_INFO_MIN_OFFSET) & 0xFF; + let bus_freq_mhz = (__cpuid(0x16).ecx & 0xffff) as u64; + + Ok(min_ratio * bus_freq_mhz) + } + } + /// Get the current frequency of the current CPU. fn get_curr_cpu_freq() -> Result { // Check if the CPU supports the IA32_PERF_MPERF and IA32_PERF_APERF MSRs. From ea64da03ee0312fed0c05703dfd50266d64d749d Mon Sep 17 00:00:00 2001 From: Kanata9020 <270539432+Kanata9020@users.noreply.github.com> Date: Thu, 22 Oct 2026 22:27:58 +0900 Subject: [PATCH 2/2] fix(arch): use Hz instead of MHz in x86_64 Dvfs implementation --- awkernel_lib/src/arch/x86_64/dvfs.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/awkernel_lib/src/arch/x86_64/dvfs.rs b/awkernel_lib/src/arch/x86_64/dvfs.rs index 3583288bb..ed3251f52 100644 --- a/awkernel_lib/src/arch/x86_64/dvfs.rs +++ b/awkernel_lib/src/arch/x86_64/dvfs.rs @@ -20,9 +20,16 @@ const IA32_PERF_APERF: u32 = 0xE8; const IA32_PERF_CTL: u32 = 0x199; const IA32_MISC_ENABLE: u32 = 0x1A0; +fn bus_freq_mhz() -> u64 { + match (__cpuid(0x16).ecx & 0xffff) as u64 { + 0 => 100, // Default to 100 MHz if bus frequency is not reported (old CPUs). + freq => freq, + } +} + impl Dvfs for X86 { /// Fix the frequency of the current CPU. - fn set_cpu_freq(freq_mhz: u64) -> Result<()> { + fn set_cpu_freq(freq: u64) -> Result<()> { unsafe { let mut misc_enable = Msr::new(IA32_MISC_ENABLE); let mut value = misc_enable.read(); @@ -33,9 +40,8 @@ impl Dvfs for X86 { misc_enable.write(value); } - let cpuid = __cpuid(0x16); - let bus_freq_mhz = (cpuid.ecx & 0xffff) as u64; - let target_pstate = ((freq_mhz / bus_freq_mhz) as u64) & 0xFFFF; + let bus_freq_mhz = bus_freq_mhz(); + let target_pstate = (freq / bus_freq_mhz / 1_000_000) & 0xFFFF; unsafe { let mut perf_ctl = Msr::new(IA32_PERF_CTL); let mut value = perf_ctl.read(); @@ -56,9 +62,9 @@ impl Dvfs for X86 { unsafe { let platform_info = Msr::new(MSR_PLATFORM_INFO); let max_ratio = (platform_info.read() >> MSR_PLATFORM_INFO_MAX_OFFSET) & 0xFF; - let bus_freq_mhz = (__cpuid(0x16).ecx & 0xffff) as u64; + let bus_freq_mhz = bus_freq_mhz(); - Ok(max_ratio * bus_freq_mhz) + Ok(max_ratio * bus_freq_mhz * 1_000_000) } } @@ -67,9 +73,9 @@ impl Dvfs for X86 { unsafe { let platform_info = Msr::new(MSR_PLATFORM_INFO); let min_ratio = (platform_info.read() >> MSR_PLATFORM_INFO_MIN_OFFSET) & 0xFF; - let bus_freq_mhz = (__cpuid(0x16).ecx & 0xffff) as u64; + let bus_freq_mhz = bus_freq_mhz(); - Ok(min_ratio * bus_freq_mhz) + Ok(min_ratio * bus_freq_mhz * 1_000_000) } } @@ -93,7 +99,9 @@ impl Dvfs for X86 { let mperf_delta = mperf.read(); let aperf_delta = aperf.read(); - Ok(aperf_delta * Self::get_max_cpu_freq().unwrap() / mperf_delta) + let max_cpu_freq_mhz = Self::get_max_cpu_freq()? / 1_000_000; + + Ok(aperf_delta * max_cpu_freq_mhz / mperf_delta * 1_000_000) } } }