diff --git a/rog-platform/src/asus_armoury.rs b/rog-platform/src/asus_armoury.rs index 1265b518..678d2307 100644 --- a/rog-platform/src/asus_armoury.rs +++ b/rog-platform/src/asus_armoury.rs @@ -53,6 +53,63 @@ pub struct Attribute { base_path: PathBuf, } +fn is_intel_cpu() -> bool { + std::fs::read_to_string("/proc/cpuinfo") + .map(|content| content.contains("GenuineIntel")) + .unwrap_or(false) +} + +fn write_intel_rapl_limit(constraint_idx: u32, watts: i32) { + let microwatts_str = ((watts as u64) * 1_000_000).to_string(); + let file_name = format!("constraint_{}_power_limit_uw", constraint_idx); + let Ok(entries) = read_dir("/sys/class/powercap") else { + return; + }; + for entry in entries.flatten() { + let zone = entry.file_name(); + let zone = zone.to_string_lossy(); + // A package zone name has exactly one ':' ("intel-rapl:0"). Sub-zones have two ("intel-rapl:0:0"). + let is_package_zone = (zone.starts_with("intel-rapl:") + || zone.starts_with("intel-rapl-mmio:")) + && zone.matches(':').count() == 1; + if !is_package_zone { + continue; + } + let path = entry.path().join(&file_name); + if path.exists() { + debug!("Writing {microwatts_str} to {}", path.display()); + if let Ok(mut file) = OpenOptions::new().write(true).open(&path) { + let _ = file.write_all(microwatts_str.as_bytes()); + } + } + } +} + +fn sync_all_intel_rapl_limits() { + if !is_intel_cpu() { + return; + } + + let base_dir = Path::new("/sys/class/firmware-attributes/asus-armoury/attributes"); + + let limits = [ + ("ppt_pl1_spl", 0), + ("ppt_pl2_sppt", 1), + ("ppt_pl3_fppt", 2), + ]; + + for (attr_name, constraint_idx) in &limits { + let current_value_path = base_dir.join(attr_name).join("current_value"); + if current_value_path.exists() { + if let Ok(val_str) = std::fs::read_to_string(¤t_value_path) { + if let Ok(watts) = val_str.trim().parse::() { + write_intel_rapl_limit(*constraint_idx, watts); + } + } + } + } +} + impl Attribute { pub fn name(&self) -> &str { &self.name @@ -97,6 +154,12 @@ impl Attribute { let mut file = OpenOptions::new().write(true).open(&path)?; file.write_all(value_str.as_bytes())?; + + if self.name == "ppt_pl1_spl" || self.name == "ppt_pl2_sppt" || self.name == "ppt_pl3_fppt" + { + sync_all_intel_rapl_limits(); + } + Ok(()) }