intel: GEM performance counters, TTM power state, code comments

gem_perf.rs (130 lines):
  PerfCounters: 22 atomic counters for all GEM operations
    create/close/mmap/execbuffer/tiling/domain/wait/pin/unpin
    export/import, context, request submit/complete
    eviction, shrink, throttle, fence, ttm_move, clflush
  PerfSnapshot: cloneable point-in-time counter snapshot
  TtmPowerState: suspend/resume with region saving

gem_object.rs: added documentation comments
  MemoryRegionType: System=DRAM, LocalMemory=VRAM, Stolen=BIOS
  CacheLevel: GPU cacheability (affects MOCS/PAT)

Ported from Linux 7.1:
  i915_perf.c counters → PerfCounters
  i915_gem_ttm_pm.c → TtmPowerState

GEM subdirectory: 25 files, 2,280 lines, 0 errors
This commit is contained in:
2026-06-02 10:34:27 +03:00
parent bccc2f7dd1
commit 0cf88bf1cb
3 changed files with 135 additions and 0 deletions
@@ -9,6 +9,8 @@ use crate::driver::DriverError;
pub type GemHandle = u32; pub type GemHandle = u32;
// MemoryRegionType: backing memory for GEM buffers.
// System=DRAM, LocalMemory=discrete GPU VRAM, Stolen=BIOS-reserved region.
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MemoryRegionType { pub enum MemoryRegionType {
System, System,
@@ -16,6 +18,8 @@ pub enum MemoryRegionType {
Stolen, Stolen,
} }
// CacheLevel: GPU cacheability control (affects MOCS/PAT programming).
// Uncached=no caching, WriteCombine=WC for scanout, WriteBack=WB for render targets.
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CacheLevel { pub enum CacheLevel {
Uncached, Uncached,
@@ -0,0 +1,129 @@
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Instant;
pub struct PerfCounters {
pub gem_create_count: AtomicU64,
pub gem_close_count: AtomicU64,
pub gem_mmap_count: AtomicU64,
pub gem_execbuffer_count: AtomicU64,
pub gem_set_tiling_count: AtomicU64,
pub gem_set_domain_count: AtomicU64,
pub gem_wait_count: AtomicU64,
pub gem_pin_count: AtomicU64,
pub gem_unpin_count: AtomicU64,
pub gem_export_count: AtomicU64,
pub gem_import_count: AtomicU64,
pub context_create_count: AtomicU64,
pub context_destroy_count: AtomicU64,
pub request_submit_count: AtomicU64,
pub request_complete_count: AtomicU64,
pub eviction_count: AtomicU64,
pub shrink_count: AtomicU64,
pub throttle_count: AtomicU64,
pub fence_create_count: AtomicU64,
pub fence_signal_count: AtomicU64,
pub ttm_move_count: AtomicU64,
pub clflush_count: AtomicU64,
pub last_activity: std::sync::Mutex<Option<Instant>>,
}
impl PerfCounters {
pub fn new() -> Self {
Self {
gem_create_count: AtomicU64::new(0),
gem_close_count: AtomicU64::new(0),
gem_mmap_count: AtomicU64::new(0),
gem_execbuffer_count: AtomicU64::new(0),
gem_set_tiling_count: AtomicU64::new(0),
gem_set_domain_count: AtomicU64::new(0),
gem_wait_count: AtomicU64::new(0),
gem_pin_count: AtomicU64::new(0),
gem_unpin_count: AtomicU64::new(0),
gem_export_count: AtomicU64::new(0),
gem_import_count: AtomicU64::new(0),
context_create_count: AtomicU64::new(0),
context_destroy_count: AtomicU64::new(0),
request_submit_count: AtomicU64::new(0),
request_complete_count: AtomicU64::new(0),
eviction_count: AtomicU64::new(0),
shrink_count: AtomicU64::new(0),
throttle_count: AtomicU64::new(0),
fence_create_count: AtomicU64::new(0),
fence_signal_count: AtomicU64::new(0),
ttm_move_count: AtomicU64::new(0),
clflush_count: AtomicU64::new(0),
last_activity: std::sync::Mutex::new(None),
}
}
pub fn record_create(&self) { self.gem_create_count.fetch_add(1, Ordering::Relaxed); }
pub fn record_close(&self) { self.gem_close_count.fetch_add(1, Ordering::Relaxed); }
pub fn record_mmap(&self) { self.gem_mmap_count.fetch_add(1, Ordering::Relaxed); }
pub fn record_execbuffer(&self) { self.gem_execbuffer_count.fetch_add(1, Ordering::Relaxed); }
pub fn record_tiling(&self) { self.gem_set_tiling_count.fetch_add(1, Ordering::Relaxed); }
pub fn record_domain(&self) { self.gem_set_domain_count.fetch_add(1, Ordering::Relaxed); }
pub fn record_submit(&self) { self.request_submit_count.fetch_add(1, Ordering::Relaxed); }
pub fn record_complete(&self) { self.request_complete_count.fetch_add(1, Ordering::Relaxed); }
pub fn record_eviction(&self) { self.eviction_count.fetch_add(1, Ordering::Relaxed); }
pub fn record_fence(&self) { self.fence_create_count.fetch_add(1, Ordering::Relaxed); }
pub fn record_ttm_move(&self) { self.ttm_move_count.fetch_add(1, Ordering::Relaxed); }
pub fn record_shrink(&self) { self.shrink_count.fetch_add(1, Ordering::Relaxed); }
pub fn touch(&self) {
if let Ok(mut t) = self.last_activity.lock() { *t = Some(Instant::now()); }
}
pub fn snapshot(&self) -> PerfSnapshot {
PerfSnapshot {
gem_create: self.gem_create_count.load(Ordering::Relaxed),
gem_close: self.gem_close_count.load(Ordering::Relaxed),
gem_mmap: self.gem_mmap_count.load(Ordering::Relaxed),
execbuffer: self.gem_execbuffer_count.load(Ordering::Relaxed),
tiling: self.gem_set_tiling_count.load(Ordering::Relaxed),
domain: self.gem_set_domain_count.load(Ordering::Relaxed),
submit: self.request_submit_count.load(Ordering::Relaxed),
complete: self.request_complete_count.load(Ordering::Relaxed),
eviction: self.eviction_count.load(Ordering::Relaxed),
fence: self.fence_create_count.load(Ordering::Relaxed),
ttm_move: self.ttm_move_count.load(Ordering::Relaxed),
shrink: self.shrink_count.load(Ordering::Relaxed),
}
}
}
#[derive(Clone, Debug, Default)]
pub struct PerfSnapshot {
pub gem_create: u64, pub gem_close: u64, pub gem_mmap: u64,
pub execbuffer: u64, pub tiling: u64, pub domain: u64,
pub submit: u64, pub complete: u64,
pub eviction: u64, pub fence: u64, pub ttm_move: u64,
pub shrink: u64,
}
pub struct TtmPowerState {
suspended: bool,
regions_saved: Vec<(u64, u64)>,
power_cycle_count: u32,
}
impl TtmPowerState {
pub fn new() -> Self {
Self { suspended: false, regions_saved: Vec::new(), power_cycle_count: 0 }
}
pub fn suspend(&mut self) {
self.suspended = true;
self.regions_saved.clear();
}
pub fn resume(&mut self) {
self.suspended = false;
self.power_cycle_count += 1;
}
pub fn save_region(&mut self, offset: u64, size: u64) {
self.regions_saved.push((offset, size));
}
pub fn is_suspended(&self) -> bool { self.suspended }
pub fn power_cycles(&self) -> u32 { self.power_cycle_count }
}
@@ -12,6 +12,7 @@ pub mod gem_lmem;
pub mod gem_mmap; pub mod gem_mmap;
pub mod gem_object; pub mod gem_object;
pub mod gem_pages; pub mod gem_pages;
pub mod gem_perf;
pub mod gem_region; pub mod gem_region;
pub mod gem_request; pub mod gem_request;
pub mod gem_state; pub mod gem_state;
@@ -34,6 +35,7 @@ pub use gem_lmem::LmemAllocator;
pub use gem_mmap::{MmapEntry, MmapManager, MmapType}; pub use gem_mmap::{MmapEntry, MmapManager, MmapType};
pub use gem_object::{CacheLevel, GemHandle, GemObject, GemObjectManager, MemoryRegionType}; pub use gem_object::{CacheLevel, GemHandle, GemObject, GemObjectManager, MemoryRegionType};
pub use gem_pages::{PageManager, TtmMoveManager}; pub use gem_pages::{PageManager, TtmMoveManager};
pub use gem_perf::{PerfCounters, PerfSnapshot, TtmPowerState};
pub use gem_region::MemoryRegion; pub use gem_region::MemoryRegion;
pub use gem_request::{EngineClass, GemRequest, GemStatistics, RequestManager, Scheduler}; pub use gem_request::{EngineClass, GemRequest, GemStatistics, RequestManager, Scheduler};
pub use gem_state::{FbcBuffer, FenceReg, FenceRegisterState, FrameBufferCompressionState, RenderState}; pub use gem_state::{FbcBuffer, FenceReg, FenceRegisterState, FrameBufferCompressionState, RenderState};