diff --git a/config/redbear-device-services.toml b/config/redbear-device-services.toml index feb7ed0b19..d95e69dcec 100644 --- a/config/redbear-device-services.toml +++ b/config/redbear-device-services.toml @@ -484,7 +484,7 @@ requires_weak = ["04_drivers.target"] [service] cmd = "/usr/bin/coretempd" -type = "oneshot_async" +type = { scheme = "coretemp" } """ [[files]] diff --git a/config/redbear-mini.toml b/config/redbear-mini.toml index 9e56968303..12b9f60e4c 100644 --- a/config/redbear-mini.toml +++ b/config/redbear-mini.toml @@ -501,7 +501,7 @@ requires_weak = ["00_base.target"] [service] cmd = "inputd" args = ["-A", "2"] -type = "oneshot" +type = "oneshot_async" """ [[files]] diff --git a/local/recipes/system/coretempd/source/src/main.rs b/local/recipes/system/coretempd/source/src/main.rs index 7dda64ea2f..5892c96d49 100644 --- a/local/recipes/system/coretempd/source/src/main.rs +++ b/local/recipes/system/coretempd/source/src/main.rs @@ -298,7 +298,9 @@ fn run_daemon() -> Result<(), String> { let mut scheme = CoretempScheme::new(cpu_infos); if let Some(fd) = notify_fd { - notify_scheme_ready(fd, &socket, &mut scheme)?; + if let Err(e) = notify_scheme_ready(fd, &socket, &mut scheme) { + eprintln!("[WARN] coretempd: init notification failed ({}), continuing without notify", e); + } } eprintln!("[INFO] coretempd: registered scheme:coretemp"); diff --git a/local/recipes/system/cpufreqd/source/src/main.rs b/local/recipes/system/cpufreqd/source/src/main.rs index 94824ba937..d81bbdadf0 100644 --- a/local/recipes/system/cpufreqd/source/src/main.rs +++ b/local/recipes/system/cpufreqd/source/src/main.rs @@ -1,6 +1,8 @@ use std::env; use std::fs; use std::io::{Read, Write}; +use std::process::Command; +use std::sync::atomic::{AtomicBool, Ordering}; use std::time::{Duration, Instant}; const IA32_PERF_CTL: u32 = 0x199; @@ -10,6 +12,8 @@ const STATE_WRITE_INTERVAL_S: u64 = 1; const MSR_ERROR_SUPPRESS_COUNT: u32 = 1; const THERMAL_CACHE_MS: u64 = 1000; +static MSR_AVAILABLE: AtomicBool = AtomicBool::new(true); + #[derive(Clone, Copy, PartialEq, Debug)] enum Governor { Performance, Powersave, Ondemand, Conservative, Schedutil } @@ -57,7 +61,7 @@ fn read_acpi_pss(cpu: u32) -> Vec { ] } -fn write_msr(cpu: u32, msr: u32, val: u64) -> bool { +fn write_msr_raw(cpu: u32, msr: u32, val: u64) -> bool { let path = format!("/scheme/sys/msr/{}/{:x}", cpu, msr); fs::OpenOptions::new().write(true).open(&path).ok() .and_then(|mut f| { @@ -66,6 +70,33 @@ fn write_msr(cpu: u32, msr: u32, val: u64) -> bool { }).is_some() } +fn write_msr(cpu: u32, msr: u32, val: u64) -> bool { + if !MSR_AVAILABLE.load(Ordering::Relaxed) { + return false; + } + let path = format!("/scheme/sys/msr/{}/{:x}", cpu, msr); + fs::OpenOptions::new().write(true).open(&path).ok() + .and_then(|mut f| { + let hex_val = format!("{:016x}", val); + f.write_all(hex_val.as_bytes()).ok() + }).is_some() +} + +fn probe_msr_available(cpu: u32) -> bool { + let exe = match env::current_exe() { + Ok(p) => p, + Err(_) => return false, + }; + match Command::new(exe) + .arg("--probe-msr") + .arg(cpu.to_string()) + .status() + { + Ok(s) => s.success(), + Err(_) => false, + } +} + fn measure_load(cpu: u32, prev: &mut (u64, u64)) -> f64 { if let Ok(d) = fs::read_to_string(format!("/scheme/sys/cpu/{}/stat", cpu)) { let p: Vec = d.split_whitespace().filter_map(|s| s.parse().ok()).collect(); @@ -116,6 +147,15 @@ fn write_scheme_state(governor: Governor, cpus: &[CpuInfo]) { } fn main() { + let args: Vec = env::args().collect(); + + // Probe mode: child process tests MSR write and exits with status. + if args.len() >= 3 && args[1] == "--probe-msr" { + let cpu: u32 = args[2].parse().unwrap_or(0); + let ok = write_msr_raw(cpu, IA32_PERF_CTL, 0x1a00); + std::process::exit(if ok { 0 } else { 1 }); + } + let governor = match env::var("CPUFREQ_GOVERNOR").unwrap_or_default().as_str() { "performance" => Governor::Performance, "powersave" => Governor::Powersave, "conservative" => Governor::Conservative, "schedutil" => Governor::Schedutil, @@ -123,6 +163,18 @@ fn main() { }; let cpus = detect_cpus(); eprintln!("[INFO] cpufreqd: detected {} CPU(s), governor={:?}", cpus.len(), governor); + + // Probe MSR availability before attempting any writes. + // In environments without MSR 0x199 (QEMU default, some hypervisors), + // wrmsr causes a kernel #GP that kills the process. By spawning a child + // to test the write first, we detect this safely and degrade to + // monitoring-only mode. + let msr_ok = cpus.iter().all(|&id| probe_msr_available(id)); + if !msr_ok { + MSR_AVAILABLE.store(false, Ordering::Relaxed); + eprintln!("[INFO] cpufreqd: MSR 0x199 writes unavailable — running in monitoring-only mode"); + } + let mut ci: Vec = cpus.iter().map(|&id| { let ps = read_acpi_pss(id); eprintln!("[INFO] cpufreqd: CPU{}: {} P-states ({} - {} kHz)", id, ps.len(), ps.first().map_or(0, |p| p.freq_khz), ps.last().map_or(0, |p| p.freq_khz)); diff --git a/local/recipes/system/driver-manager/source/src/config.rs b/local/recipes/system/driver-manager/source/src/config.rs index ec365b9d0b..39da6953b0 100644 --- a/local/recipes/system/driver-manager/source/src/config.rs +++ b/local/recipes/system/driver-manager/source/src/config.rs @@ -106,7 +106,7 @@ impl DriverConfig { driver.r#match.into_iter().map(DriverMatch::from).collect(); if matches.is_empty() { - log::warn!( + log::debug!( "driver-manager: config {} driver={} has no match entries and will not bind from PCI or ACPI enumeration", path.display(), driver.name