From 10eeebdc374f00468eb37822af28a5b54edeff8b Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Mon, 1 Jun 2026 21:11:05 +0300 Subject: [PATCH] =?UTF-8?q?intel:=20Phase=202=20=E2=80=94=20memory=20manag?= =?UTF-8?q?ement=20modernization?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - mod.rs: identity PPGTT with 2MB-pages, PDP register programming in cs_submit - lmem.rs: free-list page allocator replacing simple bump allocator - ring.rs: expose write_reg as pub(crate) for PDP register access --- .../source/src/drivers/intel/lmem.rs | 54 +++++++++++++++++-- .../redox-drm/source/src/drivers/intel/mod.rs | 48 ++++++++++++++++- .../source/src/drivers/intel/ring.rs | 2 +- 3 files changed, 97 insertions(+), 7 deletions(-) diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/lmem.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/lmem.rs index 2938cb0eb4..66be9e4c69 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/lmem.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/lmem.rs @@ -1,4 +1,4 @@ -use log::info; +use log::{debug, info}; use redox_driver_sys::memory::MmioRegion; @@ -25,6 +25,8 @@ pub struct IntelLmem { bar_addr: u64, bar_size: u64, next_offset: u64, + free_list: Vec<(u64, u64)>, + total_allocated: u64, } impl IntelLmem { @@ -43,29 +45,73 @@ impl IntelLmem { bar_addr, bar_size, next_offset: 0, + free_list: Vec::new(), + total_allocated: 0, }) } pub fn alloc(&mut self, size: u64, alignment: u64) -> Result { + let aligned_size = align_up(size, alignment); + + if let Some(idx) = self + .free_list + .iter() + .position(|&(start, free_size)| { + let aligned_start = align_up(start, alignment); + aligned_start + aligned_size <= start + free_size + }) + { + let (free_start, free_size) = self.free_list.remove(idx); + let aligned = align_up(free_start, alignment); + let remainder = (aligned + aligned_size).saturating_sub(free_start); + if remainder < free_size { + self.free_list + .push((free_start + remainder, free_size - remainder)); + } + self.total_allocated += aligned_size; + let vram_addr = self.bar_addr + aligned; + debug!( + "redox-drm-intel: LMEM reused {:#x} bytes at offset {:#x} (phys {:#010x}) from free list", + aligned_size, aligned, vram_addr + ); + return Ok(vram_addr); + } + let aligned = align_up(self.next_offset, alignment); let end = aligned - .checked_add(size) + .checked_add(aligned_size) .ok_or_else(|| DriverError::Buffer("Intel LMEM allocation overflow".into()))?; if end > self.bar_size { return Err(DriverError::Buffer(format!( "Intel LMEM exhausted: need {:#x} at offset {:#x}, have {:#x}", - size, aligned, self.bar_size + aligned_size, aligned, self.bar_size ))); } self.next_offset = end; + self.total_allocated += aligned_size; let vram_addr = self.bar_addr + aligned; info!( "redox-drm-intel: LMEM allocated {:#x} bytes at offset {:#x} (phys {:#010x})", - size, aligned, vram_addr + aligned_size, aligned, vram_addr ); Ok(vram_addr) } + pub fn free(&mut self, offset: u64, size: u64) { + let aligned_size = align_up(size, 4096); + self.free_list.push((offset, aligned_size)); + self.free_list.sort_by_key(|&(start, _)| start); + self.total_allocated = self.total_allocated.saturating_sub(aligned_size); + debug!( + "redox-drm-intel: LMEM freed {:#x} bytes at offset {:#x}, {} regions in free list", + aligned_size, offset, self.free_list.len() + ); + } + + pub fn allocated_bytes(&self) -> u64 { + self.total_allocated + } + pub fn vram_mmio(&self) -> &MmioRegion { &self.mmio } diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs index 137bc155cc..0063966df2 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs @@ -89,7 +89,6 @@ const RING_HEAD_OFFSET: usize = 0x34; const GEN8_PDP0_UDW: usize = 0x270; const GEN8_PDP0_LDW: usize = 0x274; -const GEN8_PDP_STRIDE: usize = 8; pub struct IntelDriver { info: PciDeviceInfo, @@ -290,7 +289,11 @@ impl IntelDriver { let mut ring = IntelRing::create(mmio_arc.clone(), RingType::Render)?; ring.bind_gtt(&mut gtt)?; - let (default_pd_base, has_ppgtt) = setup_identity_ppgtt(&mut gtt, &device_info)?; + let (default_pd_base, has_ppgtt) = if device_info.is_gen9_or_later() { + setup_identity_ppgtt(&mut gtt)? + } else { + (0, false) + }; let mut guc = GucFirmware::new(mmio_arc.clone()); if let Some(guc_key) = device_info.guc_fw_key { @@ -1018,6 +1021,14 @@ impl GpuDriver for IntelDriver { let mut ring = self.ring.lock() .map_err(|_| DriverError::Initialization("Intel ring state poisoned".into()))?; + + if self.has_ppgtt && self.default_pd_base != 0 { + let pd_lo = (self.default_pd_base & 0xFFFF_FFFF) as u32; + let pd_hi = ((self.default_pd_base >> 32) & 0xFFFF_FFFF) as u32; + ring.write_reg(GEN8_PDP0_LDW, pd_lo)?; + ring.write_reg(GEN8_PDP0_UDW, pd_hi)?; + } + ring.submit_batch(cmds)?; let seqno = ring.last_seqno(); drop(ring); @@ -1261,3 +1272,36 @@ fn discover_vbt(mmio: &MmioRegion) -> Option { debug!("redox-drm-intel: no VBT found in MMIO, using port heuristic"); None } + +fn setup_identity_ppgtt(gtt: &mut IntelGtt) -> Result<(u64, bool)> { + use redox_driver_sys::dma::DmaBuffer; + + let pd_bytes = 4096usize; + let mut pd_buf = DmaBuffer::allocate(pd_bytes, 4096) + .map_err(|e| DriverError::Buffer(format!("PPGTT PD DMA alloc failed: {e}")))?; + let pd_phys = pd_buf.physical_address() as u64; + + let pd_slice = unsafe { + std::slice::from_raw_parts_mut(pd_buf.as_mut_ptr(), pd_bytes) + }; + + for entry in 0..128u64 { + let page_addr = entry * 0x200000; + let pte_val = page_addr + | (1u64 << 0) + | (1u64 << 1) + | (1u64 << 7); + let offset = (entry as usize) * 8; + pd_slice[offset..offset + 8].copy_from_slice(&pte_val.to_le_bytes()); + } + + let pd_gpu_addr = gtt.alloc_range(pd_bytes as u64)?; + gtt.map_range(pd_gpu_addr, pd_phys, pd_bytes as u64, (1u64 << 0) | (1u64 << 1))?; + + info!( + "redox-drm-intel: identity PPGTT PD at {:#010x} (phys {:#010x}, 128 × 2MB entries, covers {}MB)", + pd_gpu_addr, pd_phys, 128 * 2 + ); + + Ok((pd_gpu_addr, true)) +} diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/ring.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/ring.rs index 041ea74671..a4417033e1 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/ring.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/ring.rs @@ -239,7 +239,7 @@ impl IntelRing { Ok(self.mmio.read32(offset)) } - fn write_reg(&self, reg: usize, value: u32) -> Result<()> { + pub(crate) fn write_reg(&self, reg: usize, value: u32) -> Result<()> { let offset = self .base .checked_add(reg)