redbear-power: consume real /scheme/coretemp and /scheme/sys/cpu sources
This commit is contained in:
@@ -2,12 +2,16 @@
|
||||
//!
|
||||
//! Probes the host kernel once at startup and selects the correct
|
||||
//! path for each data source (MSR, ACPI PSS, /proc/stat, cpufreq
|
||||
//! sysfs, hwmon temperatures). On Redox OS the `/scheme/sys/...`
|
||||
//! sysfs, hwmon temperatures). On Red Bear OS the `/scheme/sys/...`
|
||||
//! paths are tried first; on Linux the equivalent `/dev/cpu/*/msr`,
|
||||
//! `/proc/stat`, and `/sys/devices/system/cpu/cpu*/cpufreq/` paths
|
||||
//! are used as fallbacks so the TUI shows live data on a developer
|
||||
//! host too.
|
||||
//!
|
||||
//! Red Bear OS data sources are now real (not stubs): the kernel
|
||||
//! serves hardware MSRs through `/scheme/sys/msr/` and per-CPU
|
||||
//! scheduler statistics through `/scheme/sys/cpu/{n}/stat`.
|
||||
//!
|
||||
//! Each probe emits exactly one `eprintln!` line at startup naming
|
||||
//! the data source and the failure mode. This matches cpu-x's
|
||||
//! `MSG_VERBOSE` pattern (core.cpp:380-410) and lets the user know
|
||||
|
||||
@@ -11,16 +11,19 @@
|
||||
//! - `curr*_input` — current in milli-Amps
|
||||
//! - `*_label` — human-readable label for the corresponding `_input`
|
||||
//!
|
||||
//! On Redox, the `hwmon` scheme is not yet implemented, so when the sysfs
|
||||
//! path is absent the module falls back to reading the CPU package
|
||||
//! temperature via the `IA32_THERM_STATUS` MSR exposed through
|
||||
//! `/scheme/sys/msr/`.
|
||||
//! On Red Bear OS the thermal surface is provided by daemons:
|
||||
//! - `/scheme/thermal/zones/` — thermal zones from `thermald` (ACPI + CPU die)
|
||||
//! - `/scheme/coretemp/` — per-CPU die temperatures from `coretempd`
|
||||
//! - `/scheme/sys/msr/` — direct MSR fallback for CPU package temperature
|
||||
//!
|
||||
//! The Redox sources are preferred over the Linux sysfs path when present.
|
||||
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
const SYS_HWMON: &str = "/sys/class/hwmon";
|
||||
const REDOX_THERMAL: &str = "/scheme/thermal";
|
||||
const REDOX_CORETEMP: &str = "/scheme/coretemp";
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct SensorReading {
|
||||
@@ -175,6 +178,37 @@ fn read_redox_thermal_zones() -> Vec<HwmonChip> {
|
||||
chips
|
||||
}
|
||||
|
||||
/// Enumerate Redox `/scheme/coretemp/` directories and return one
|
||||
/// `HwmonChip`-like entry per CPU with a temperature reading.
|
||||
fn read_redox_coretemp() -> Vec<HwmonChip> {
|
||||
let root = Path::new(REDOX_CORETEMP);
|
||||
let Ok(entries) = fs::read_dir(root) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let mut chips = Vec::new();
|
||||
for entry in entries.flatten() {
|
||||
let name = match entry.file_name().into_string() {
|
||||
Ok(n) => n,
|
||||
Err(_) => continue,
|
||||
};
|
||||
let temp_path = root.join(&name).join("temperature");
|
||||
let Some(temp_raw) = read_sysfs_i64(&temp_path) else {
|
||||
continue;
|
||||
};
|
||||
chips.push(HwmonChip {
|
||||
name: "coretemp".to_string(),
|
||||
path: root.join(&name),
|
||||
readings: vec![SensorReading {
|
||||
kind: SensorKind::Temp,
|
||||
label: Some(format!("CPU {}", name)),
|
||||
raw_value: temp_raw * 1000,
|
||||
display_value: format_sensor(SensorKind::Temp, temp_raw * 1000),
|
||||
}],
|
||||
});
|
||||
}
|
||||
chips
|
||||
}
|
||||
|
||||
/// Read all `*_input` files in the chip directory, grouped by prefix.
|
||||
fn read_chip_readings(chip_dir: &Path) -> Vec<SensorReading> {
|
||||
let entries = match fs::read_dir(chip_dir) {
|
||||
@@ -250,6 +284,12 @@ impl SensorInfo {
|
||||
return Self { chips };
|
||||
}
|
||||
}
|
||||
if Path::new(REDOX_CORETEMP).exists() {
|
||||
let chips = read_redox_coretemp();
|
||||
if !chips.is_empty() {
|
||||
return Self { chips };
|
||||
}
|
||||
}
|
||||
let Ok(dirs) = fs::read_dir(SYS_HWMON) else {
|
||||
if let Some(temp_c) = read_first_cpu_temp_msr() {
|
||||
return Self {
|
||||
|
||||
Reference in New Issue
Block a user