This commit is contained in:
Ilya Zlobintsev 2025-01-04 09:56:01 +02:00
parent 02e4e400e0
commit 9c100b058d
6 changed files with 132 additions and 6 deletions

View File

@ -5,7 +5,7 @@ fn main() {
println!("cargo:rustc-link-lib=drm_amdgpu");
println!("cargo:rustc-link-lib=drm_intel");
println!("cargo::rerun-if-changed=wrapper/");
println!("cargo::rerun-if-changed=wrapper");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());

View File

@ -4,18 +4,21 @@ use super::GpuController;
use crate::{config, server::vulkan::get_vulkan_info};
use amdgpu_sysfs::gpu_handle::power_profile_mode::PowerProfileModesTable;
use anyhow::{anyhow, Context};
use drm::bindings::i915;
use drm::{bindings, i915};
use futures::future::LocalBoxFuture;
use lact_schema::{
ClocksInfo, ClocksTable, ClockspeedStats, DeviceInfo, DeviceStats, DrmInfo, GpuPciInfo,
IntelClocksTable, IntelDrmInfo, LinkInfo, PowerStates, VramStats,
};
use std::{
cell::Cell,
fmt::Display,
fs,
io::{BufRead, BufReader},
os::{fd::AsRawFd, raw::c_int},
path::{Path, PathBuf},
str::FromStr,
time::Instant,
};
use tracing::{debug, error, info, trace, warn};
@ -32,6 +35,7 @@ pub struct IntelGpuController {
pci_info: GpuPciInfo,
tile_gts: Vec<PathBuf>,
drm_file: fs::File,
last_gpu_busy: Cell<Option<(Instant, u64)>>,
}
impl IntelGpuController {
@ -95,6 +99,7 @@ impl IntelGpuController {
pci_info,
tile_gts,
drm_file,
last_gpu_busy: Cell::new(None),
})
}
}
@ -219,10 +224,11 @@ impl GpuController for IntelGpuController {
clockspeed,
vram: VramStats {
total: self
.drm_try_2(i915::drm_intel_get_aperture_sizes)
.drm_try_2(bindings::i915::drm_intel_get_aperture_sizes)
.map(|(_, total)| total as u64),
used: None,
},
busy_percent: self.get_busy_percent(),
..Default::default()
}
}
@ -279,10 +285,20 @@ impl GpuController for IntelGpuController {
}
impl IntelGpuController {
fn debugfs_path(&self) -> PathBuf {
#[cfg(test)]
return PathBuf::from("/dev/null");
Path::new("/sys/kernel/debug/dri").join(&self.pci_slot_id)
}
fn first_tile_gt(&self) -> Option<&Path> {
self.tile_gts.first().map(PathBuf::as_ref)
}
/// Based on the input path, this has the following behaviour:
/// - Basic relative paths are resolved relative to the sysfs device
/// - Parent paths (starting with (../) are resolved on the sysfs card entry, without resolving device symlink
fn sysfs_file_path(&self, path: impl AsRef<Path>) -> PathBuf {
let path = path.as_ref();
@ -358,8 +374,8 @@ impl IntelGpuController {
fn get_drm_info_i915(&self) -> IntelDrmInfo {
IntelDrmInfo {
execution_units: self.drm_try(i915::drm_intel_get_eu_total),
subslices: self.drm_try(i915::drm_intel_get_subslice_total),
execution_units: self.drm_try(bindings::i915::drm_intel_get_eu_total),
subslices: self.drm_try(bindings::i915::drm_intel_get_subslice_total),
}
}
@ -405,4 +421,41 @@ impl IntelGpuController {
}
}
}
#[allow(
clippy::cast_precision_loss,
clippy::cast_sign_loss,
clippy::cast_possible_truncation
)]
fn get_busy_percent(&self) -> Option<u8> {
let path = self.debugfs_path().join("gt0/rps_boost");
let file = fs::File::open(path).ok()?;
let mut lines = BufReader::new(file).lines();
while let Some(Ok(line)) = lines.next() {
if let Some(contents) = line.strip_prefix("GPU busy?") {
let raw_value = contents
.split_ascii_whitespace()
.last()?
.strip_suffix("ms")?;
let gpu_busy: u64 = raw_value.parse().ok()?;
let timestamp = Instant::now();
if let Some((last_timestamp, last_gpu_busy)) =
self.last_gpu_busy.replace(Some((timestamp, gpu_busy)))
{
let time_delta = timestamp - last_timestamp;
let gpu_busy_delta = gpu_busy - last_gpu_busy;
println!("time delta: {time_delta:?}, busy delta: {gpu_busy_delta}");
let percentage =
(gpu_busy_delta as f64 / time_delta.as_millis() as f64) * 100.0;
return Some(percentage as u8);
}
}
}
None
}
}

View File

@ -1,2 +1,3 @@
pub mod bindings;
pub mod i915;
pub mod xe;

View File

@ -0,0 +1,71 @@
/*#![allow(
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::cast_sign_loss
)]
use crate::server::gpu_controller::intel::drm::bindings::i915::{
drm_i915_query, DRM_COMMAND_BASE, DRM_I915_QUERY_TOPOLOGY_INFO, DRM_IOCTL_BASE,
};
use nix::{errno::Errno, ioctl_readwrite};
use std::{alloc, fs::File, mem, os::fd::AsRawFd};
use super::bindings::i915::{
drm_i915_query_item, drm_i915_query_topology_info, DRM_I915_QUERY_HWCONFIG_BLOB,
};
const DRM_I915_QUERY: u32 = 0x39;
ioctl_readwrite!(
i915_device_query,
DRM_IOCTL_BASE,
DRM_COMMAND_BASE + DRM_I915_QUERY,
drm_i915_query
);
unsafe fn query_item(fd: i32, item: &mut drm_i915_query_item) -> Result<(), Errno> {
let query_items = [*item];
let mut query = drm_i915_query {
num_items: query_items.len() as u32,
flags: 0,
items_ptr: query_items.as_ptr() as u64,
};
i915_device_query(fd, &mut query)?;
*item = query_items[0];
Ok(())
}
pub fn query_hwconfig(fd: &File) -> Result<(), Errno> {
let fd = fd.as_raw_fd();
unsafe {
let mut item = drm_i915_query_item {
query_id: DRM_I915_QUERY_HWCONFIG_BLOB as u64,
length: 0,
flags: 0,
data_ptr: 0,
};
query_item(fd, &mut item)?;
if item.length <= 0 {
println!("Nothing found");
return Ok(());
}
println!("asd");
// let layout = alloc::Layout::from_size_align(
// item.length as usize,
// mem::align_of::<drm_i915_query_topology_info>(),
// )
// .unwrap();
// #[allow(clippy::cast_ptr_alignment)]
// let topology_info = alloc::alloc(layout) as *const drm_i915_query_topology_info;
// item.data_ptr = topology_info as u64;
// item.data_ptr = println!("query result: {item:?}");
}
Ok(())
}*/

View File

@ -1,5 +1,5 @@
/*use super::bindings::xe::{drm_xe_device_query, DRM_XE_DEVICE_QUERY, DRM_XE_DEVICE_QUERY_ENGINES};
use crate::server::gpu_controller::intel::bindings::xe::{
use crate::server::gpu_controller::intel::drm::bindings::xe::{
drm_xe_query_engines, DRM_COMMAND_BASE, DRM_IOCTL_BASE, DRM_XE_DEVICE_QUERY_HWCONFIG,
};
use nix::{errno::Errno, ioctl_readwrite};

View File

@ -1 +1,2 @@
#include "drm/i915_drm.h"
#include "libdrm/intel_bufmgr.h"