From ac7c5b1761abdbb07be9c359751e99ee5fe31b8f Mon Sep 17 00:00:00 2001 From: Vasilito Date: Fri, 15 May 2026 07:23:25 +0100 Subject: [PATCH] fix: align MMIO mappings to page boundaries for VirtIO capabilities VirtIO capability structures can start at non-page-aligned offsets within\nBARs. The kernel physmap requires page-aligned addresses. Align the physical\naddress down, adjust the size, and apply the page offset to the returned\npointer. Track the original map pointer/size separately for correct unmapping. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- .../redox-driver-sys/source/src/memory.rs | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/local/recipes/drivers/redox-driver-sys/source/src/memory.rs b/local/recipes/drivers/redox-driver-sys/source/src/memory.rs index 6292649a8e..ae7279404b 100644 --- a/local/recipes/drivers/redox-driver-sys/source/src/memory.rs +++ b/local/recipes/drivers/redox-driver-sys/source/src/memory.rs @@ -81,6 +81,8 @@ fn ensure_memory_root() -> Result { pub struct MmioRegion { ptr: *mut u8, size: usize, + map_ptr: *mut u8, + map_size: usize, } impl MmioRegion { @@ -89,7 +91,13 @@ impl MmioRegion { return Err(DriverError::InvalidAddress(phys_addr)); } - let aligned_size = size.next_multiple_of(PAGE_SIZE); + // Align physical address down to page boundary for physmap compatibility. + // The kernel requires page-aligned addresses; VirtIO capabilities can + // start at non-page-aligned offsets within BARs. + let page_offset = (phys_addr as usize) % PAGE_SIZE; + let aligned_phys = phys_addr - page_offset as u64; + let adjusted_size = size + page_offset; + let aligned_size = adjusted_size.next_multiple_of(PAGE_SIZE); let path = format!("physical@{}", cache.suffix()); let mode = if prot.contains(MmioProt::READ | MmioProt::WRITE) { @@ -112,7 +120,7 @@ impl MmioRegion { let mem_fd = root_fd.openat(&path, (O_CLOEXEC | mode) as i32, 0)?; let map = Map { - offset: phys_addr as usize, + offset: aligned_phys as usize, size: aligned_size, flags: mmap_prot | redox_syscall::MapFlags::from_bits_truncate(MAP_SHARED.bits()), address: 0, @@ -127,8 +135,10 @@ impl MmioRegion { })?; Ok(Self { - ptr: ptr as *mut u8, - size: aligned_size, + ptr: unsafe { (ptr as *mut u8).add(page_offset) }, + size, + map_ptr: ptr as *mut u8, + map_size: aligned_size, }) } @@ -290,8 +300,8 @@ impl MmioRegion { impl Drop for MmioRegion { fn drop(&mut self) { - if !self.ptr.is_null() { - let _ = unsafe { libredox::call::munmap(self.ptr as *mut (), self.size) }; + if !self.map_ptr.is_null() { + let _ = unsafe { libredox::call::munmap(self.map_ptr as *mut (), self.map_size) }; } } }