lscpu
: Read CPU count from sysfs
, add freq_boost status to output
This commit is contained in:
@ -7,7 +7,6 @@ use clap::{crate_version, Arg, ArgAction, Command};
|
|||||||
use regex::RegexBuilder;
|
use regex::RegexBuilder;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::{cmp, fs};
|
use std::{cmp, fs};
|
||||||
use sysinfo::System;
|
|
||||||
use uucore::{error::UResult, format_usage, help_about, help_usage};
|
use uucore::{error::UResult, format_usage, help_about, help_usage};
|
||||||
|
|
||||||
mod options {
|
mod options {
|
||||||
@ -72,8 +71,6 @@ struct OutputOptions {
|
|||||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let matches: clap::ArgMatches = uu_app().try_get_matches_from(args)?;
|
let matches: clap::ArgMatches = uu_app().try_get_matches_from(args)?;
|
||||||
|
|
||||||
let system = System::new_all();
|
|
||||||
|
|
||||||
let output_opts = OutputOptions {
|
let output_opts = OutputOptions {
|
||||||
_hex: matches.get_flag(options::HEX),
|
_hex: matches.get_flag(options::HEX),
|
||||||
json: matches.get_flag(options::JSON),
|
json: matches.get_flag(options::JSON),
|
||||||
@ -91,18 +88,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||||||
arch_info.add_child(CpuInfo::new("Address sizes", &addr_sizes, None))
|
arch_info.add_child(CpuInfo::new("Address sizes", &addr_sizes, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(byte_order) = fs::read_to_string("/sys/kernel/cpu_byteorder") {
|
if let Some(byte_order) = sysfs::read_cpu_byte_order() {
|
||||||
match byte_order.trim() {
|
arch_info.add_child(CpuInfo::new("Byte Order", byte_order, None));
|
||||||
"big" => arch_info.add_child(CpuInfo::new("Byte Order", "Big Endian", None)),
|
|
||||||
"little" => arch_info.add_child(CpuInfo::new("Byte Order", "Little Endian", None)),
|
|
||||||
_ => eprintln!("Unrecognised Byte Order: {}", byte_order),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cpu_topology = sysfs::read_cpu_topology();
|
||||||
|
|
||||||
cpu_infos.push(arch_info);
|
cpu_infos.push(arch_info);
|
||||||
cpu_infos.push(CpuInfo::new(
|
cpu_infos.push(CpuInfo::new(
|
||||||
"CPU(s)",
|
"CPU(s)",
|
||||||
&format!("{}", system.cpus().len()),
|
&format!("{}", cpu_topology.cpus.len()),
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -123,6 +118,15 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||||||
model_name_info.add_child(CpuInfo::new("Model", &model, None));
|
model_name_info.add_child(CpuInfo::new("Model", &model, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(freq_boost_enabled) = sysfs::read_freq_boost_state() {
|
||||||
|
let s = if freq_boost_enabled {
|
||||||
|
"enabled"
|
||||||
|
} else {
|
||||||
|
"disabled"
|
||||||
|
};
|
||||||
|
model_name_info.add_child(CpuInfo::new("Frequency boost", s, None));
|
||||||
|
}
|
||||||
|
|
||||||
vendor_info.add_child(model_name_info);
|
vendor_info.add_child(model_name_info);
|
||||||
}
|
}
|
||||||
cpu_infos.push(vendor_info);
|
cpu_infos.push(vendor_info);
|
||||||
@ -211,6 +215,8 @@ fn find_cpuinfo_value(contents: &str, key: &str) -> Option<String> {
|
|||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This is non-exhaustive and assumes that compile-time arch is the same as runtime
|
||||||
|
// This is not always guaranteed to be the case, ie. you can run a x86 binary on a x86_64 machine
|
||||||
fn get_architecture() -> String {
|
fn get_architecture() -> String {
|
||||||
if cfg!(target_arch = "x86") {
|
if cfg!(target_arch = "x86") {
|
||||||
"x86".to_string()
|
"x86".to_string()
|
||||||
|
@ -5,6 +5,60 @@ pub struct CpuVulnerability {
|
|||||||
pub mitigation: String,
|
pub mitigation: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CpuTopology {
|
||||||
|
pub cpus: Vec<Cpu>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Cpu {
|
||||||
|
_index: usize,
|
||||||
|
_caches: Vec<CpuCache>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CpuCache {
|
||||||
|
_index: usize,
|
||||||
|
_typ: String,
|
||||||
|
_level: String,
|
||||||
|
_size: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This should go through each CPU in sysfs and calculate things such as cache sizes and physical topology
|
||||||
|
// For now it just returns a list of CPUs which are enabled
|
||||||
|
pub fn read_cpu_topology() -> CpuTopology {
|
||||||
|
let mut out: Vec<Cpu> = vec![];
|
||||||
|
|
||||||
|
// NOTE: All examples I could find was where this file contains a CPU index range in the form of `<start>-<end>`
|
||||||
|
// Theoretically, there might be a situation where some cores are disabled, so that `enabled` cannot be represented
|
||||||
|
// as a continuous range. For now we just assume it's always `X-Y` and use those as our bounds to read CPU information
|
||||||
|
let enabled_cpus = match fs::read_to_string("/sys/devices/system/cpu/enabled") {
|
||||||
|
Ok(content) => {
|
||||||
|
let parts: Vec<_> = content
|
||||||
|
.trim()
|
||||||
|
.split("-")
|
||||||
|
.flat_map(|part| part.parse::<usize>())
|
||||||
|
.collect();
|
||||||
|
assert_eq!(parts.len(), 2);
|
||||||
|
(parts[0], parts[1])
|
||||||
|
}
|
||||||
|
Err(e) => panic!("Could not read sysfs: {}", e),
|
||||||
|
};
|
||||||
|
|
||||||
|
for cpu_index in enabled_cpus.0..(enabled_cpus.1 + 1) {
|
||||||
|
out.push(Cpu {
|
||||||
|
_index: cpu_index,
|
||||||
|
_caches: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
CpuTopology { cpus: out }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_freq_boost_state() -> Option<bool> {
|
||||||
|
match fs::read_to_string("/sys/devices/system/cpu/cpufreq/boost") {
|
||||||
|
Ok(content) => Some(content.trim() == "1"),
|
||||||
|
Err(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read_cpu_vulnerabilities() -> Vec<CpuVulnerability> {
|
pub fn read_cpu_vulnerabilities() -> Vec<CpuVulnerability> {
|
||||||
let mut out: Vec<CpuVulnerability> = vec![];
|
let mut out: Vec<CpuVulnerability> = vec![];
|
||||||
|
|
||||||
@ -31,3 +85,14 @@ pub fn read_cpu_vulnerabilities() -> Vec<CpuVulnerability> {
|
|||||||
|
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_cpu_byte_order() -> Option<&'static str> {
|
||||||
|
if let Ok(byte_order) = fs::read_to_string("/sys/kernel/cpu_byteorder") {
|
||||||
|
match byte_order.trim() {
|
||||||
|
"big" => return Some("Big Endian"),
|
||||||
|
"little" => return Some("Little Endian"),
|
||||||
|
_ => eprintln!("Unrecognised Byte Order: {}", byte_order),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user