#[cfg(target_os = "linux")]
pub(super) fn read_drm_vram_mib(device_path: &std::path::Path) -> u64 {
let direct = device_path.join("mem_info_vram_total");
if let Ok(s) = std::fs::read_to_string(&direct) {
if let Ok(bytes) = s.trim().parse::<u64>() {
return bytes / 1024 / 1024;
}
}
let drm_dir = device_path.join("drm");
if let Ok(entries) = std::fs::read_dir(&drm_dir) {
for entry in entries.flatten() {
let candidate = entry.path().join("device").join("mem_info_vram_total");
if let Ok(s) = std::fs::read_to_string(&candidate) {
if let Ok(bytes) = s.trim().parse::<u64>() {
return bytes / 1024 / 1024;
}
}
}
}
0
}
#[cfg(not(target_os = "linux"))]
pub(super) fn read_drm_vram_mib(_device_path: &std::path::Path) -> u64 {
0
}
#[cfg(target_os = "linux")]
pub(super) fn host_pci_address_from_sysfs(device_path: &std::path::Path) -> String {
let Some(name) = device_path.file_name().and_then(|n| n.to_str()) else {
return String::new();
};
if let Some(rest) = name.strip_prefix("0000:") {
return rest.to_string();
}
name.to_string()
}
#[cfg(not(target_os = "linux"))]
pub(super) fn host_pci_address_from_sysfs(_device_path: &std::path::Path) -> String {
String::new()
}
#[cfg(target_os = "linux")]
pub(super) fn read_drm_serial(device_path: &std::path::Path) -> Option<String> {
for fname in &["serial_number", "serial"] {
let path = device_path.join(fname);
if let Ok(s) = std::fs::read_to_string(&path) {
let trimmed = s.trim().to_string();
if !trimmed.is_empty() && trimmed != "0" {
return Some(trimmed);
}
}
}
None
}
#[cfg(not(target_os = "linux"))]
pub(super) fn read_drm_serial(_device_path: &std::path::Path) -> Option<String> {
None
}
#[cfg(target_os = "linux")]
pub(super) fn read_pci_bdf_from_drm_card(card_dir: &std::path::Path) -> Option<String> {
let target = std::fs::read_link(card_dir.join("device")).ok()?;
target
.file_name()
.and_then(|n| n.to_str())
.map(|s| s.to_string())
}
#[cfg(target_os = "linux")]
pub(super) fn read_intel_vram_resident_bytes(bdf_filter: Option<&str>) -> Option<u64> {
let proc_dir = std::fs::read_dir("/proc").ok()?;
let mut total_bytes: u64 = 0;
let mut found_any_intel_client = false;
for proc_entry in proc_dir.flatten() {
let pid_name = proc_entry.file_name();
let Some(pid_str) = pid_name.to_str() else {
continue;
};
if !pid_str.bytes().all(|b| b.is_ascii_digit()) {
continue;
}
let fdinfo_dir = proc_entry.path().join("fdinfo");
let Ok(fd_entries) = std::fs::read_dir(&fdinfo_dir) else {
continue;
};
for fd_entry in fd_entries.flatten() {
let Ok(content) = std::fs::read_to_string(fd_entry.path()) else {
continue;
};
if !content.contains("drm-driver:") {
continue;
}
let is_intel = content
.lines()
.filter_map(|l| l.strip_prefix("drm-driver:"))
.any(|v| {
let v = v.trim();
v == "i915" || v == "xe"
});
if !is_intel {
continue;
}
if let Some(want_bdf) = bdf_filter {
let matches = content
.lines()
.filter_map(|l| l.strip_prefix("drm-pdev:"))
.any(|v| v.trim() == want_bdf);
if !matches {
continue;
}
}
found_any_intel_client = true;
for line in content.lines() {
if let Some(rest) = line.strip_prefix("drm-resident-local0:") {
if let Some(bytes) = parse_drm_size(rest) {
total_bytes = total_bytes.saturating_add(bytes);
}
}
}
}
}
if found_any_intel_client {
Some(total_bytes)
} else {
None
}
}
#[cfg(target_os = "linux")]
fn parse_drm_size(s: &str) -> Option<u64> {
let trimmed = s.trim();
let mut parts = trimmed.split_whitespace();
let num: u64 = parts.next()?.parse().ok()?;
let unit = parts.next().unwrap_or("B");
let multiplier: u64 = match unit {
"B" | "" => 1,
"KiB" => 1024,
"MiB" => 1024 * 1024,
"GiB" => 1024 * 1024 * 1024,
_ => return None,
};
Some(num.saturating_mul(multiplier))
}