diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/gem_dispatch.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/gem_dispatch.rs new file mode 100644 index 0000000000..6c2d8b86a2 --- /dev/null +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/gem_dispatch.rs @@ -0,0 +1,136 @@ +use std::sync::Arc; +use std::sync::Mutex; + +use crate::driver::{DriverError, Result}; +use super::gem_object::{GemObjectManager, MemoryRegionType}; +use super::gem_create::CreateManager; +use super::gem_context::ContextManager; +use super::gem_mmap::MmapManager; +use super::gem_tiling::TilingManager; + +pub struct GemIoctlDispatch { + pub object_manager: Arc>, + pub context_manager: Arc>, + pub mmap_manager: Arc>, + pub tiling_manager: Arc>, +} + +impl GemIoctlDispatch { + pub fn new( + om: GemObjectManager, cm: ContextManager, + mm: MmapManager, tm: TilingManager, + ) -> Self { + Self { + object_manager: Arc::new(Mutex::new(om)), + context_manager: Arc::new(Mutex::new(cm)), + mmap_manager: Arc::new(Mutex::new(mm)), + tiling_manager: Arc::new(Mutex::new(tm)), + } + } + + pub fn create(&self, size: u64, region: MemoryRegionType) -> Result { + let params = super::gem_create::CreateParams::new(size); + let mut om = self.object_manager.lock().map_err(|e| + DriverError::Initialization("GEM lock poisoned".into()))?; + CreateManager::create(¶ms, &mut om) + } + + pub fn close(&self, handle: u32) -> Result<()> { + let mut om = self.object_manager.lock().map_err(|e| + DriverError::Initialization("GEM lock poisoned".into()))?; + om.close(handle) + } + + pub fn pin(&self, handle: u32) -> Result<()> { + let mut om = self.object_manager.lock().map_err(|e| + DriverError::Initialization("GEM lock poisoned".into()))?; + om.pin(handle) + } + + pub fn unpin(&self, handle: u32) -> Result<()> { + let mut om = self.object_manager.lock().map_err(|e| + DriverError::Initialization("GEM lock poisoned".into()))?; + om.unpin(handle) + } + + pub fn get_size(&self, handle: u32) -> Result { + let om = self.object_manager.lock().map_err(|e| + DriverError::Initialization("GEM lock poisoned".into()))?; + Ok(om.get(handle)?.size) + } + + pub fn set_cache(&self, handle: u32, level: super::gem_object::CacheLevel) -> Result<()> { + let mut om = self.object_manager.lock().map_err(|e| + DriverError::Initialization("GEM lock poisoned".into()))?; + om.set_cache_level(handle, level) + } + + pub fn set_gtt_offset(&self, handle: u32, offset: u64) -> Result<()> { + let mut om = self.object_manager.lock().map_err(|e| + DriverError::Initialization("GEM lock poisoned".into()))?; + om.set_gtt_offset(handle, offset) + } + + pub fn context_create(&self, name: Option<&str>, ppgtt: bool) -> Result { + let mut cm = self.context_manager.lock().map_err(|e| + DriverError::Initialization("GEM lock poisoned".into()))?; + cm.create(name, ppgtt) + } + + pub fn context_destroy(&self, handle: u32) -> Result<()> { + let mut cm = self.context_manager.lock().map_err(|e| + DriverError::Initialization("GEM lock poisoned".into()))?; + cm.destroy(handle) + } + + pub fn set_tiling(&self, handle: u32, mode: super::gem_tiling::TilingMode, stride: u32) -> Result<()> { + let mut tm = self.tiling_manager.lock().map_err(|e| + DriverError::Initialization("GEM lock poisoned".into()))?; + tm.set_tiling(handle, mode, stride) + } + + pub fn get_tiling(&self, handle: u32) -> Option { + self.tiling_manager.lock().ok().and_then(|tm| tm.get_tiling(handle)) + } +} + +pub struct BufferValidator; + +impl BufferValidator { + pub fn validate_size(size: u64) -> Result<()> { + if size == 0 { + return Err(DriverError::Buffer("zero-size buffer".into())); + } + if size > 4u64 * 1024 * 1024 * 1024 { + return Err(DriverError::Buffer("buffer exceeds 4GB limit".into())); + } + Ok(()) + } + + pub fn validate_offset_length(offset: u32, length: u32, buffer_size: u64) -> Result<()> { + let end = offset as u64 + length as u64; + if end > buffer_size { + return Err(DriverError::Buffer(format!( + "offset+length {} exceeds buffer size {}", end, buffer_size + ))); + } + if length % 4 != 0 { + return Err(DriverError::Buffer("length must be DWORD-aligned".into())); + } + Ok(()) + } + + pub fn validate_alignment(alignment: u64) -> Result<()> { + if alignment == 0 || alignment % 4096 != 0 { + return Err(DriverError::Buffer("alignment must be 4K-aligned".into())); + } + Ok(()) + } + + pub fn validate_handle_list(handles: &[u32], om: &GemObjectManager) -> Result<()> { + for &h in handles { + om.get(h)?; + } + Ok(()) + } +} diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/mod.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/mod.rs index 46ef52181f..a71277b0e5 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/mod.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/mod.rs @@ -1,6 +1,7 @@ pub mod gem_backend; pub mod gem_context; pub mod gem_create; +pub mod gem_dispatch; pub mod gem_dmabuf; pub mod gem_domain; pub mod gem_evict; @@ -22,6 +23,7 @@ pub mod gem_vma; pub use gem_backend::{ClflushManager, InternalBackend, PhysBackend, ShmemBackend}; pub use gem_context::{ContextManager, ContextPriority, GemContext, create_default_context}; pub use gem_create::{CreateManager, CreateParams}; +pub use gem_dispatch::{BufferValidator, GemIoctlDispatch}; pub use gem_dmabuf::{DmaBufExport, DmaBufImport, DmaBufManager}; pub use gem_domain::{BusyManager, DomainManager, DomainState, GpuDomain, ThrottleManager}; pub use gem_evict::{EvictableObject, EvictionClass, EvictionManager, FenceObjectManager, GpuFence, WoundWaitMutex};