From ad74e920ae850c35714ee683ebec41456a55677b Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Mon, 1 Jun 2026 09:42:24 +0300 Subject: [PATCH] fix: coretempd MSR probe for QEMU default machine type On QEMU's default i440FX machine type, rdmsr on unsupported MSRs (0x19c IA32_THERM_STATUS, 0x1a2 IA32_TEMPERATURE_TARGET) causes a kernel #GP that kills the process. Same pattern as cpufreqd: spawn a child with --probe-msr to test readability before the main loop. If probe fails, disable all MSR reads and report all CPUs as Unknown. --- .../system/coretempd/source/src/main.rs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/local/recipes/system/coretempd/source/src/main.rs b/local/recipes/system/coretempd/source/src/main.rs index 5892c96d49..0a15652f84 100644 --- a/local/recipes/system/coretempd/source/src/main.rs +++ b/local/recipes/system/coretempd/source/src/main.rs @@ -1,5 +1,7 @@ use std::env; use std::fs; +use std::process::Command; +use std::sync::atomic::{AtomicBool, Ordering}; use std::thread; use std::time::Duration; @@ -17,6 +19,8 @@ const IA32_THERM_STATUS: u32 = 0x19c; const IA32_TEMPERATURE_TARGET: u32 = 0x1a2; const AMD_TCTL: u32 = 0xc0010293; +static MSR_AVAILABLE: AtomicBool = AtomicBool::new(true); + #[derive(Clone, Copy, Debug, PartialEq)] enum Vendor { Intel, @@ -25,12 +29,29 @@ enum Vendor { } fn read_msr(cpu: u32, msr: u32) -> Option { + if !MSR_AVAILABLE.load(Ordering::Relaxed) { + return None; + } let path = format!("/scheme/sys/msr/{}/{:x}", cpu, msr); fs::read_to_string(&path) .ok() .and_then(|s| u64::from_str_radix(s.trim(), 16).ok()) } +fn probe_msr_available() -> bool { + let exe = match env::current_exe() { + Ok(p) => p, + Err(_) => return false, + }; + match Command::new(exe) + .arg("--probe-msr") + .status() + { + Ok(s) => s.success(), + Err(_) => false, + } +} + fn detect_vendor(cpu: u32) -> Vendor { if read_msr(cpu, IA32_THERM_STATUS).is_some() { Vendor::Intel @@ -275,6 +296,15 @@ fn notify_scheme_ready( fn run_daemon() -> Result<(), String> { let notify_fd = init_notify_fd(); + // Probe MSR availability before attempting any reads. + // On QEMU's default machine type, rdmsr on unsupported MSRs (0x19c, 0x1a2) + // causes a kernel #GP that kills the process. By spawning a child to test + // the read first, we detect this safely and degrade to Unknown vendor. + if !probe_msr_available() { + MSR_AVAILABLE.store(false, Ordering::Relaxed); + eprintln!("[INFO] coretempd: MSR reads unavailable — reporting all CPUs as Unknown"); + } + let cpus = detect_cpus(); eprintln!("[INFO] coretempd: detected {} CPU(s)", cpus.len()); @@ -345,6 +375,13 @@ fn run_daemon() -> Result<(), String> { } fn main() { + // Probe mode: child process tests MSR read and exits with status. + let args: Vec = env::args().collect(); + if args.len() >= 2 && args[1] == "--probe-msr" { + let probe_ok = read_msr(0, IA32_THERM_STATUS).is_some(); + std::process::exit(if probe_ok { 0 } else { 1 }); + } + if let Err(e) = run_daemon() { eprintln!("[ERROR] coretempd: {e}"); std::process::exit(1);